{"id":31592388,"url":"https://github.com/noopeeks/decidim-deployment-guide","last_synced_at":"2026-05-02T23:39:14.513Z","repository":{"id":227833444,"uuid":"772178039","full_name":"NoOPeEKS/decidim-deployment-guide","owner":"NoOPeEKS","description":"A free and open-source full guide on how to setup a fully working production dockerized Decidim instance for your organization. From creating an EC2 AWS instance to its full deployment with just executing some scripts!","archived":false,"fork":false,"pushed_at":"2024-04-26T09:54:56.000Z","size":229,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-26T10:51:21.819Z","etag":null,"topics":["aws","decidim","democracy","docker","foss","guide","production"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NoOPeEKS.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-03-14T17:22:08.000Z","updated_at":"2024-04-26T10:51:22.983Z","dependencies_parsed_at":"2024-04-26T11:01:39.613Z","dependency_job_id":null,"html_url":"https://github.com/NoOPeEKS/decidim-deployment-guide","commit_stats":null,"previous_names":["noopeeks/decidim-tutorial","noopeeks/decidim-deployment-guide"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/NoOPeEKS/decidim-deployment-guide","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoOPeEKS%2Fdecidim-deployment-guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoOPeEKS%2Fdecidim-deployment-guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoOPeEKS%2Fdecidim-deployment-guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoOPeEKS%2Fdecidim-deployment-guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NoOPeEKS","download_url":"https://codeload.github.com/NoOPeEKS/decidim-deployment-guide/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoOPeEKS%2Fdecidim-deployment-guide/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278551929,"owners_count":26005477,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-06T02:00:05.630Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","decidim","democracy","docker","foss","guide","production"],"created_at":"2025-10-06T03:08:16.542Z","updated_at":"2025-10-06T03:12:50.508Z","avatar_url":"https://github.com/NoOPeEKS.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Deploying a Decidim Instance\n\n## Create an AWS EC2 Instance\nFirst, create an AWS account and go to the AWS Management Console. \\\nThen, go to the EC2 Panel and select the big orange button `Launch Instance`. \n\n![EC2 main page](./images/awsec2mainpage.png)\n\nThen, select your instance name, operating system (for this tutorial we will be using Amazon Linux x86), instance type (we will be using t2.medium, with 2 vCPUs and 4GB RAM it's enough), and generate a key pair for connecting to it through ssh. \n\nNext, set up the firewall rules as you please, but since this is meant to be a web server, you should leave it like this:\n\n![Firewall rules](./images/networkec2settings.png)\n\nFinally, set the amount of storage you will need for this server. In this case, you should at least give it 50GB of storage. Click on launch instance and you are set to go.\n\n## Connect to your AWS EC2 instance\nUsing the keypair you have created previously, execute the following command to ssh into the machine:\n```bash\nssh -i keypair.pem ec2-user@yourinstanceip\n```\n\n## Generating selfsigned certificates\nIf you haven't bought a domain, you can still use the application through self-signed SSL certificates, but browsers will raise a warning.\n```bash\nsudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./selfsigned.key -out ./selfsigned.crt\n```\nThis command should generate your self-signed certificate and private key and move it to the decidim-tutorial directory. \\\nThen, open nginx.conf and add under `listen 443 ssl;` the following lines:\n- `ssl_certificate /etc/ssl/certs/selfsigned.crt;`\n- `ssl_certificate_key /etc/ssl/certs/selfsigned.key;` \\\nThen, open nginx.Dockerfile and modify it so that the copy commands look like this:\n- `COPY nginx.conf /tmp/docker.nginx`\n- `COPY selfsigned.crt /etc/ssl/certs/selfsigned.crt`\n- `COPY selfsigned.key /etc/ssl/certs/selfsigned.key`\n\n## Generating a certificate for your specific domain using Let's Encrypt\n```bash\nsudo certbot certonly --standalone -d subdomain.domain.tld -v\ncp /etc/letsencrypt/live/subdomain.domain.com/fullchain.pem .\ncp /etc/letsencrypt/live/subdomain.domain.com/privkey.pem .\n```\nThese commands should generate your certificate and private key and move it to the decidim-tutorial directory. \\\nThen, open nginx.conf and add under `listen 443 ssl;` the following lines:\n- `ssl_certificate /etc/ssl/certs/fullchain.pem;`\n- `ssl_certificate_key /etc/ssl/certs/privkey.pem;` \\\nThen, open nginx.Dockerfile and modify it so that the copy commands look like this:\n- `COPY nginx.conf /tmp/docker.nginx`\n- `COPY fullchain.pem /etc/ssl/certs/fullchain.pem`\n- `COPY privkey.pem /etc/ssl/certs/privkey.pem`\n\n## Creating a Docker Swarm cluster and deploying Decidim stack\nThese commands will create a docker swarm cluster to orchestrate and manage the services needed to run decidim and its services.\n```bash\nsudo docker swarm init\n```\nUpdate environment variables with your own values in `docker-compose.yml` and then execute the following commands:\n```bash\nmkdir /tmp/rails_storage ·# Or call it whatever you want but remember to change it in docker-compose.yml\nsudo docker-compose build\nsudo docker stack deploy -c docker-compose.yml decidim-tutorial\n```\n\n## Creating a System Admin User\nTo create a System Admin User, you only need to execute some simple commands and follow the prompt:\n```bash\nsudo docker exec -it $(sudo docker ps | grep ghcr | awk '{print $1}') /bin/bash\nbundle exec rake decidim_system:create_admin\n```\n\n## Creating a New Organization\n\nVisit `https://localhost:443` or `subdomain.domain.tld`, and log in with the system user you have created. Fill the form with your organization's data and set `localhost` or `subdomain.domain.tld` as the host.\n\n### SMTP Server config and Organization Admin Creation\n\nIn Decidim 0.28.0 there is a bug that will not allow to set your smtp server from the system panel [`error when saving smtp password for organization #12535`](https://github.com/decidim/decidim/issues/12535), as if you introduce a password, it will crash and not create a new organization. Leave those fields empty, as you should have already configured your SMTP server in `docker-compose.yml`.\n\nFill the Organization Admin fields with its name and its email. Decidim will send an email to the provided address. Follow the steps to create an admin account.\n\n## Customize Your Organization\n\nNavigate to `https://localhost:443/` or `subdomain.domain.tld` and log in as the user you just updated.\nCustomize the website to your preferences!\n\n## Set Up a Cron Job to backup Decidim's database\nFirstly, create an S3 Bucket from your AWS Console and set your EC2 instance permissions to access this bucket.\nThen, edit the S3 URL inside `cron-backup-pg.sh` to match your bucket's URL. You probably just need to change it to your bucket's name.\nThen, change the required names for your Postgres user and Database.\nFinally, execute the following commands to set up a Cron Job that backs up the database every 7 days.\n```bash\nsudo dnf install cronie\nchmod +x cron-backup-pg.sh\nsudo crontab -e\n0 0 */7 * * /home/ec2-user/decidim-deployment-guide/scripts/cron-backup-pg.sh # Paste this inside the text editor and exit\n```\n## How to renew certificates\nLet's Encrypt's SSL certificates have an expiry date of 90 days. This means that in order for your domain to remain secure, they need to be renewed before they expire.\nTo do so, execute the following command:\n```bash\nsudo certbot renew\n```\nThen copy the fullchain.pem from the route that is output to you to the repository's folder and build the image again. Then, redeploy the service and your certificates will be updated right away.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoopeeks%2Fdecidim-deployment-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnoopeeks%2Fdecidim-deployment-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoopeeks%2Fdecidim-deployment-guide/lists"}