Redmine 6.1.6 on AWS User Guide
Overview
This guide covers launching and using the Redmine 6.1.6 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg help desk, IT service and project management listing on AWS Marketplace; you choose it as the software version when you launch.
Redmine is an open source project management and issue tracking web application. Each project gets its own issue tracker with configurable trackers, statuses and workflows, plus time tracking, a Gantt chart and calendar, a wiki, news, documents, files and forums, with roles and permissions per project. Teams use it as a bug tracker, a service desk queue or a general work tracker.
What the cloudimg image adds:
- No default login. Upstream Redmine's first administrator is the published
admin/admin. On this image first boot replaces that password with one generated for your instance, soadmin/adminnever works, and Redmine's own check on Administration, Information shows "Default administrator account changed". - Sign in required, self registration off. From the first page load every page asks for a sign in, and nobody can create an account without an administrator.
- Nothing baked into the image. The image ships an empty MySQL data directory, no secret key and no certificate. First boot creates this instance's database, runs Redmine's migrations and default data, and generates its secret key, certificate and administrator password.
- No database password at all. Redmine runs as its own system user,
redmine, and MySQL accepts it only over the local socket from processes running as that user (auth_socketauthentication). MySQL has no network listener. - HTTPS from the first boot. nginx serves Redmine on port 443 with a certificate generated on your instance, port 80 redirects to HTTPS, and a request for a host name the instance does not serve gets no answer.
- Puma behind nginx only. Redmine runs in Puma as the
redmineuser on a unix socket that only nginx can reach. nginx serves the precompiled assets from disk and passes your real client address to Redmine, so its sign in log and lockout cannot be fooled with anX-Forwarded-Forheader. - Sign in attempts rate limited. nginx limits sign in attempts per client address.
- Read only code. The code under
/opt/redmineand its configuration in/etc/redmineare owned by root; theredmineuser can write only its attachments, temporary files and logs. - No ImageMagick or Ghostscript. Thumbnails and the Gantt PNG export are optional in Redmine, and leaving these out removes the image converter attack surface.
- The build toolchain removed. Redmine's gems are a fixed, reviewed set installed at build time; compilers and development headers are removed before the image is captured.
- Metadata access blocked. nginx, Puma, MySQL and first boot are blocked from the instance metadata service, and the AMI requires IMDSv2.
- Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
What is on the image: Redmine 6.1.6 (the upstream release redmine-6.1.6.tar.gz, checksum verified) with Rails 7.2, Puma 8, Ruby 3.2, nginx, MySQL 8.0, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.
Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route you use for management).
- A security group that allows TCP 22 (SSH) from your admin network, and TCP 443 (Redmine) and TCP 80 (redirects to HTTPS) from the networks your users are on. Keep 80 and 443 as narrow as you can.
Step 1: Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Redmine 6.1.6 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large (or larger for many users), your key pair and a security group as above.
With the AWS CLI (replace the values in angle brackets):
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=redmine}]'
First boot builds the database and takes about two minutes after the instance is running.
Step 2: Connect to your instance
| Version | SSH user |
|---|---|
| Redmine 6.1.6 on Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Step 3: Check the services
First boot creates the database, sets the password and mints the certificate; nginx and Redmine start only after it has finished:
systemctl is-active nginx redmine mysql
sudo test -f /var/lib/cloudimg/redmine-firstboot.done && echo FIRSTBOOT_DONE
All three are active and the first boot marker is present:
active
active
active
FIRSTBOOT_DONE
Only SSH and nginx listen on network ports. Puma and MySQL listen on local sockets only:
sudo ss -lntp | awk 'NR>1 && $4 !~ /^127\.0\.0\.5[34]/ {split($6, p, "\""); print $4, p[2]}' | sort
sudo ss -lxp | grep -oE '/run/redmine/puma.sock|/var/run/mysqld/mysqld.sock' | sort -u
0.0.0.0:22 sshd
0.0.0.0:443 nginx
0.0.0.0:80 nginx
[::]:22 sshd
[::]:443 nginx
[::]:80 nginx
/run/redmine/puma.sock
/var/run/mysqld/mysqld.sock
Step 4: Get your URL and password
sudo cat /root/redmine-credentials.txt
The file is readable by root only:
# Redmine 6.1.6 - generated on first boot by redmine-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret.
REDMINE_URL=https://ec2-203-0-113-10.compute-1.amazonaws.com/
REDMINE_ADMIN_USER=admin
REDMINE_ADMIN_PASSWORD=<generated on your instance>
#
# Open REDMINE_URL in a browser (self-signed certificate minted on this instance's first boot; port 80 redirects to
# https) and sign in with the user and password above. Then change the password (My account > Change password), or add
# your own administrators and lock admin.
# Sign-in is required for every page and self-registration is off (Administration > Settings > Authentication).
# E-mail: not configured; add your SMTP service to /etc/redmine/configuration.yml (see the guide).
# MySQL: unix socket only (no TCP listener); Redmine signs in as the OS user redmine (auth_socket, no database
# password). root signs in over the socket: sudo mysql redmine
# Attachments: /var/lib/redmine/files Logs: journalctl -u redmine
# Change the name it serves as: sudo redmine-set-hostname <your-dns-name>
# User guide: https://www.cloudimg.co.uk/guides/redmine-6-1-6-on-ubuntu-24-04-aws/
REDMINE_URL uses the instance's public DNS name until you set your own (Step 8).
Step 5: Sign in and change the password
Open REDMINE_URL in your browser. The certificate is self signed, so your browser asks you to confirm it the first time (or install your own, Step 8). Sign in as admin with the password from Step 4.

Then make the account yours:
- Open My account, Change password and set your own password.
- Under Administration, Users, add an account for each person who uses Redmine instead of sharing one, and give at least one of them administrator rights. You can then lock
admin.
Administration, Settings, Authentication shows the sign in policy the image starts with: authentication required, self registration disabled. You can also require two factor authentication here, for administrators or for everyone, and raise the minimum password length.

Step 6: Create a project and track issues
A new instance has no projects. Choose Projects, New project, give it a name and identifier, and pick the modules it uses (issue tracking, time tracking, wiki, documents and so on). Redmine's default trackers (Bug, Feature, Support), statuses, priorities and roles are already loaded.
Open the project's Issues tab and choose New issue. The list can be filtered, sorted, grouped and saved as a custom query, and exported as CSV, PDF or Atom:

Each issue has its status, priority, assignee, dates, progress, description, subtasks, related issues and watchers, and its history of notes and changes:

Add members to each project with a role (Settings, Members in the project) so they see it and can work on its issues.
Step 7: Email notifications
Redmine sends notification emails for new and updated issues once you give it an SMTP service. Email is not configured on a new instance. Add your SMTP settings (Amazon SES or your own relay) to /etc/redmine/configuration.yml under production:, keeping the existing attachments_storage_path line:
production:
attachments_storage_path: /var/lib/redmine/files
email_delivery:
delivery_method: :smtp
smtp_settings:
address: email-smtp.<region>.amazonaws.com
port: 587
enable_starttls_auto: true
authentication: :login
user_name: "<smtp-user>"
password: "<smtp-password>"
The file stays owned by root and readable only by Redmine. Restart Redmine to load it:
sudo nano /etc/redmine/configuration.yml
sudo systemctl restart redmine
Then set the sender address under Administration, Settings, Email notifications and use Send a test email on the same page.
Step 8: Your own DNS name and certificate
Point a DNS record at the instance (an Elastic IP keeps the address stable), then set the name Redmine is served as. This mints a new self signed certificate for the name, points nginx at it, sets Redmine's host name setting (used in the links in its emails), updates /root/redmine-credentials.txt, and keeps the name across reboots:
sudo redmine-set-hostname <your-domain>
To use a certificate from a public or internal certificate authority instead, copy it over the generated pair and reload nginx (running redmine-set-hostname again replaces it with a self signed one):
sudo install -m 0644 <your-domain>.crt /etc/nginx/ssl/redmine.crt
sudo install -m 0600 <your-domain>.key /etc/nginx/ssl/redmine.key
sudo nginx -t && sudo systemctl reload nginx
Step 9: Security checks
nginx serves only Redmine's pages and its precompiled assets. The configuration, source code, logs, attachments and dotfiles answer 404, the REST and repository web services are off until you turn them on, plain HTTP redirects to HTTPS, and a request for a name the instance does not serve gets no answer at all:
H=$(sudo grep '^REDMINE_URL=' /root/redmine-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/.*#\1#')
for p in /login /projects /admin /config/database.yml /Gemfile.lock /log/production.log /files/ /.git/config /issues.json /sys/fetch_changesets; do
curl -sk -o /dev/null -w "%{http_code} $p\n" --resolve "$H:443:127.0.0.1" "https://$H$p"
done
curl -s -o /dev/null -w 'http:// -> %{http_code}\n' --resolve "$H:80:127.0.0.1" "http://$H/"
curl -sk -o /dev/null -w 'unknown host name -> %{http_code}\n' --resolve "other.example:443:127.0.0.1" "https://other.example/" || true
200 /login
302 /projects
302 /admin
404 /config/database.yml
404 /Gemfile.lock
404 /log/production.log
404 /files/
404 /.git/config
403 /issues.json
403 /sys/fetch_changesets
http:// -> 301
unknown host name -> 000
/projects and /admin redirect to the sign in page. The credential check signs in through the real sign in form with your password, and confirms that a wrong password and admin/admin are refused:
sudo redmine-cred-roundtrip
Every service runs with the instance metadata service blocked:
for u in nginx redmine mysql redmine-firstboot; do echo "$u $(systemctl show -p IPAddressDeny --value $u)"; done
nginx 168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32
redmine 168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32
mysql 168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32
redmine-firstboot 168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32
The code is owned by root, and the configuration is readable only by Redmine:
stat -c '%U:%G %a %n' /opt/redmine /opt/redmine/app /opt/redmine/config/routes.rb
sudo stat -c '%U:%G %a %n' /etc/redmine /etc/redmine/database.yml /etc/redmine/configuration.yml
root:root 755 /opt/redmine
root:root 755 /opt/redmine/app
root:root 644 /opt/redmine/config/routes.rb
root:redmine 750 /etc/redmine
root:redmine 640 /etc/redmine/database.yml
root:redmine 640 /etc/redmine/configuration.yml
Administration, Information confirms the version and Redmine's own checks. The ImageMagick lines are marked because ImageMagick is deliberately not installed (thumbnails and the Gantt PNG export are optional). The queue adapter line is informational: Redmine sends its emails in the background inside Puma, which suits a single instance.

Step 10: Backups and maintenance
Everything Redmine stores is in the MySQL database redmine (/var/lib/mysql) and its attachments under /var/lib/redmine/files. Both are on the root volume, so the simplest backup is an EBS snapshot of it. For a consistent copy you can keep elsewhere:
sudo mysqldump --single-transaction redmine | gzip > <backup-dir>/redmine-$(date +%F).sql.gz
sudo tar -C / -czf <backup-dir>/redmine-files-$(date +%F).tar.gz var/lib/redmine/files etc/redmine
Redmine's own tasks run as the redmine user with the same metadata block as the service. For example, to count projects and issues from the command line:
sudo systemd-run --quiet --pipe --wait --collect -p User=redmine -p Group=redmine -p WorkingDirectory=/opt/redmine \
-p EnvironmentFile=/etc/redmine/secret.env -p "IPAddressDeny=169.254.169.254/32 fd00:ec2::254/128" \
-E RAILS_ENV=production -E HOME=/var/lib/redmine/home -E TMPDIR=/var/lib/redmine/tmp \
/usr/local/bin/bundle exec rails runner 'puts "#{Project.count} projects, #{Issue.count} issues"'
Operating system security updates install automatically; run sudo apt-get update && sudo apt-get upgrade to apply everything else. nginx, Redmine and MySQL restart cleanly and Redmine keeps all of its data. New Redmine releases arrive as new versions of this listing, and support can help you move your data to one. Plugins and themes need gems and migrations matched to the release; ask support before adding one.
| Component | Path |
|---|---|
| Redmine code | /opt/redmine (owned by root, read only to Redmine) |
| Configuration | /etc/redmine/database.yml, /etc/redmine/configuration.yml |
| Secret key | /etc/redmine/secret.env (root only, passed to Puma by systemd) |
| Database | MySQL database redmine (/var/lib/mysql) |
| Attachments | /var/lib/redmine/files |
| Logs | journalctl -u redmine, /var/log/nginx |
| Puma socket | /run/redmine/puma.sock (2 workers) |
| nginx site | /etc/nginx/sites-available/cloudimg-redmine |
| Certificate and key | /etc/nginx/ssl/redmine.crt, /etc/nginx/ssl/redmine.key |
| Helpers | /usr/local/sbin/redmine-set-hostname, /usr/local/sbin/redmine-cred-roundtrip |
| Credentials | /root/redmine-credentials.txt (mode 0600) |
| Source and changes | /usr/share/doc/redmine-cloudimg/SOURCE.txt |
Step 11: Security recommendations
- Allow port 22 from your admin network only, and ports 80 and 443 only from the networks your users are on.
- Use your own DNS name and a certificate your browsers trust (Step 8).
- Change the
adminpassword as soon as you sign in, give each person their own account, and consider requiring two factor authentication for administrators (Step 5). - Turn on the REST API (Administration, Settings, API) only if you use it, and give each integration its own user and key.
- Keep the operating system patched, and snapshot the root volume regularly.
Support and licensing
Redmine is open source under the GNU General Public License version 2 or later, by Jean-Philippe Lang and the Redmine contributors; there is no per user licence fee. The image ships the release exactly as published, with a fixed set of Ruby gems, minus the files listed in /usr/share/doc/redmine-cloudimg/SOURCE.txt, which also names the release and its checksum.
- Email: support@cloudimg.co.uk
- Website: https://www.cloudimg.co.uk
- Support: 24/7, with a 24 hour response SLA
All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.