Applications AWS

OpenProject 17.9.6 on AWS User Guide

| Product: OpenProject 17.9.6 on Ubuntu 24.04 on AWS

Overview

This guide covers launching and using the OpenProject 17.9.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 pick it as the software version when you subscribe and launch.

OpenProject is open source project management software for classic, agile and hybrid teams. A project holds its work packages (tasks, milestones, features, bugs, user stories) with their types, statuses, assignees and dates; you plan them on a Gantt chart, move them across boards, run sprints from the backlog, and track time and costs, meetings, news and a wiki alongside them. OpenProject 17.9.6 is the vendor's own Ubuntu package of the Community edition.

What the cloudimg image adds:

  • Nothing baked into the image. The image ships with no database, no administrator password and no secret key. First boot creates the PostgreSQL database with OpenProject's demo projects, a new 128 character SECRET_KEY_BASE for signing sessions (replacing the fixed default that every OpenProject package install shares), a certificate for the instance and a password for the administrator admin unique to your instance.
  • No default logins. OpenProject's well known admin / admin sign in is never usable. The image's self test (Step 3) confirms that your password is accepted and that common passwords such as admin, changeme and openproject are refused.
  • HTTPS from the first boot. nginx serves OpenProject 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.
  • Only nginx is on the network. The OpenProject web server (Puma on 127.0.0.1:6000) and PostgreSQL listen on the loopback address only, PostgreSQL accepts local socket connections only, and the only open ports are 22, 80 and 443.
  • The configured host name and the real client address. nginx passes OpenProject the instance's configured name whatever Host or X-Forwarded-* headers a client sends, and the address of the connection itself, so OpenProject's failed sign in log and its lock after repeated wrong passwords see the real client. OpenProject itself also refuses any other host name.
  • Metadata access blocked. nginx, the OpenProject web server, its background job worker, PostgreSQL, first boot and the openproject-manage helper are blocked from the instance metadata service, so an address a user enters (a webhook, a storage or an integration URL) can never reach it, and the AMI requires IMDSv2.
  • No calls home from your team's browsers. OpenProject's security badge (an image loaded from the vendor's release server with your installation's ID and version) and Gravatar avatars (loaded from gravatar.com with a hash of each user's e-mail address) are switched off, so the pages your team opens load only from your instance.
  • No unpatched extras. OpenProject's package asks for ImageMagick, Tesseract OCR and catdoc, whose Ubuntu 24.04 security fixes are published only through Ubuntu Pro. The image does not install them (Step 7 shows how to add them with Ubuntu Pro), so nothing on the image is waiting for a fix you cannot get.
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.

What is on the image: OpenProject 17.9.6 Community edition (the vendor's package from its signed apt repository, version and checksum pinned, with its own Ruby 4.0.9 under /opt/openproject), PostgreSQL 16, nginx, 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 (OpenProject) and TCP 80 (redirects to HTTPS) from the networks your team works from. Your plans and documents are in OpenProject, so keep 80 and 443 as narrow as you can.
  • Room for attachments. Files your team attaches to work packages are stored on the root volume. Give the instance a larger root volume at launch (Step 1) if you expect many of them.

Step 1: Launch the instance

In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick OpenProject 17.9.6 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large (or larger for a big team), your key pair and a security group as above, and under Configure storage set the root volume to the size your attachments need (for example 50 GiB).

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> \
  --block-device-mappings 'DeviceName=/dev/sda1,Ebs={VolumeSize=50,VolumeType=gp3}' \
  --metadata-options HttpTokens=required,HttpEndpoint=enabled \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=openproject}]'

First boot creates the database and loads the demo projects. It takes about three minutes after the instance is running. The web server starts only when it has finished and needs about one more minute before it answers, so allow four to five minutes in all.

Step 2: Connect to your instance

Version SSH user
OpenProject 17.9.6 on Ubuntu 24.04 ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>

Step 3: Check the services

Wait until OpenProject answers. This returns as soon as the sign-in page loads, or gives up after five minutes:

timeout 300 bash -c 'until [ "$(curl -sk -o /dev/null -w "%{http_code}" https://localhost/login)" = 200 ]; do sleep 5; done' && echo OPENPROJECT_READY
OPENPROJECT_READY

PostgreSQL, the OpenProject web server (openproject-app), its background job worker (openproject-jobs) and nginx are running, and first boot has finished:

systemctl is-active postgresql@16-main openproject-app openproject-jobs nginx
sudo test -f /var/lib/cloudimg/openproject-firstboot.done && echo FIRSTBOOT_DONE
active
active
active
active
FIRSTBOOT_DONE

Only SSH and nginx listen on the network. The OpenProject web server and PostgreSQL listen on the loopback address:

sudo ss -lntp | awk 'NR>1 && $4 !~ /^127\.0\.0\.5[34]/ {split($6, p, "\""); print $4, p[2]}' | sort
0.0.0.0:22 sshd
0.0.0.0:443 nginx
0.0.0.0:80 nginx
127.0.0.1:5432 postgres
127.0.0.1:6000 ruby
[::]:22 sshd
[::]:443 nginx
[::]:80 nginx

The image's self test checks the open ports, signs in with your password, confirms that common passwords and anonymous API calls are refused, and checks the HTTPS redirect. It takes about a minute:

sudo openproject-selftest.sh
[ports] off-box TCP exactly [22 80 443]; Puma 127.0.0.1:6000; PostgreSQL loopback
[ports] OPENPROJECT_PORTS_OK
[login] per-instance credential signs in (admin, the API session works, signed out again); weak and upstream-default passwords refused; anonymous API refused
[login] OPENPROJECT_LOGIN_OK
[http] port 80 redirects to https://<configured host>/
OPENPROJECT_SELFTEST_OK

Step 4: Get your URL and password

sudo cat /root/openproject-credentials.txt

The file is readable by root only:

# OpenProject 17.9.6 on Ubuntu 24.04 by cloudimg
# Generated on this instance's first boot. These credentials are unique to THIS instance.

openproject.url=https://<public-dns-name>/
openproject.admin.login=admin
openproject.admin.password=<OPENPROJECT_ADMIN_PASSWORD>

# Sign in at the URL above with this username and password, then change the password and the administrator's e-mail
# address in OpenProject (My account). The certificate is a self-signed certificate made for this instance on its
# first boot: compare its SHA-256 fingerprint (sudo openssl x509 -in /etc/ssl/openproject/openproject.crt -noout
# -fingerprint -sha256) or replace it with a CA-issued certificate (see the user guide). Change the served name with
# sudo openproject-set-hostname <name>.

Step 5: Sign in

Open the openproject.url in your browser. The certificate is self signed, so your browser asks you to confirm it the first time; compare the fingerprint with the command in the credentials file, or install your own certificate (Step 8). Sign in with the username admin and the password from Step 4:

The OpenProject sign in page with the Username and Password fields and the Sign in button

After signing in you see OpenProject's home page, with the menu of modules on the left:

The OpenProject home page with the Welcome to OpenProject panel, the module menu (Projects, Work packages, Gantt charts, Boards, Meetings, Time and costs, Wiki) and the My meetings panel

The administrator account does not ask for a new password at the first sign in: its password was generated for this instance alone, so it is not a shared default. The administrator's e-mail address is a placeholder (admin@example.net). Open My account (the round badge at the top right), set your own e-mail address and choose a new password, then delete or update openproject.admin.password in /root/openproject-credentials.txt so it does not hold an old password. Add each member of your team under Administration, Users and permissions, and give them roles in the projects they work on.

If you lose the administrator password, set a new one from the shell. The password is read from the terminal (16 to 128 letters and digits) and never appears on a command line; the command also unlocks the admin account:

sudo openproject-set-admin-password

Step 6: Projects, work packages and plans

First boot loads OpenProject's two demo projects, so you can see each module with real content. Projects lists them; create your own with Add, and archive or delete the demo projects when you no longer need them:

The OpenProject Active projects list with the Demo project and the Scrum project, both On track and public

Work packages are the tasks, milestones and other items of a project, in a hierarchy with their type, status, assignee and priority. Click a row to open its details, comments and attachments:

The OpenProject Work packages list of the Demo project with summary tasks, tasks and milestones, their statuses and the OpenProject Admin assignee

The Gantt chart shows the same work packages on a timeline, with their dependencies; drag a bar to move or stretch it:

The OpenProject Gantt chart of the Demo project with the conference tasks and milestones laid out from November to December

For agile teams, the Backlogs module of the Scrum project holds the user stories and bugs in the backlog, ready to be planned into sprints:

The OpenProject Backlog and sprints page of the Scrum project with user stories and a bug in the Inbox backlog bucket

The REST API. OpenProject's API v3 is at /api/v3. Every request needs a signed in user or an API token: create a token under My account, Access tokens, and send it as the password of HTTP basic authentication with the user name apikey. A token has the rights of the user it belongs to. Without one, the API answers 401:

H=$(sudo grep '^openproject.url=' /root/openproject-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
curl -sk -o /dev/null -w '%{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/api/v3/projects"
401

Step 7: E-mail and other settings

OpenProject sends notifications, invitations and password reset links by e-mail. The image has no mail server, so point OpenProject at your SMTP relay under Administration, Emails and notifications, Email notifications: choose smtp as the delivery method, enter your relay's address, port, user name and password, set the Emission email address to the address OpenProject should send from, and send a test e-mail from the same page.

OpenProject's other settings are in Administration too: Authentication holds the sign in settings, including Two-factor authentication (an authenticator app or WebAuthn for each user) and Self-registration. Self registration starts as manual account activation: anyone who can reach the sign in page can ask for an account, and the account stays locked until an administrator activates it. Set it to disabled if your team's accounts are created by an administrator only.

Security badge and Gravatar. The image switches off OpenProject's security badge (an update check that loads an image from releases.openproject.com in the administrator's browser, with this installation's ID and version) and Gravatar avatars (images loaded from gravatar.com with a hash of each user's e-mail address). Users can still upload their own avatar. To turn either back on, add the line to /etc/openproject/conf.d/other and restart the services as below:

export OPENPROJECT_SECURITY__BADGE__DISPLAYED="true"
export OPENPROJECT_PLUGIN__OPENPROJECT__AVATARS_ENABLE__GRAVATARS="true"

Settings that OpenProject reads from its environment go in /etc/openproject/conf.d/other (readable by root and the openproject service account only), one export NAME="value" line each; restart the services after a change:

sudo nano /etc/openproject/conf.d/other
sudo systemctl restart openproject-app openproject-jobs

Leave /etc/openproject/conf.d/00-cloudimg as it is: first boot generated its database address, host name and SECRET_KEY_BASE for this instance, openproject-set-hostname (Step 8) rewrites it, and the services refuse to start with the placeholder the image ships.

OpenProject's own command line (rake tasks, the Rails console) runs as the openproject service account, with the same metadata block, through openproject-manage:

sudo openproject-manage rake -T
sudo openproject-manage console

Thumbnails and text in attachments. OpenProject uses ImageMagick to resize avatars and images, Tesseract to read text in attached images, and catdoc to read text in .doc, .xls and .ppt files for search. On Ubuntu 24.04 their security fixes are published only through Ubuntu Pro (ESM Apps), so the image does not install them; OpenProject checks for each tool before it uses it, and everything else works without them. To add them, attach Ubuntu Pro (free for up to 5 machines for personal use) and install them:

sudo pro attach <your-ubuntu-pro-token>
sudo apt-get install imagemagick tesseract-ocr catdoc
sudo systemctl restart openproject-app openproject-jobs

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 OpenProject is served as. This mints a new self signed certificate for the name, points nginx and OpenProject (the only name it answers, and the links in its e-mails) at it, updates the URL in /root/openproject-credentials.txt, and keeps the name across reboots:

sudo openproject-set-hostname <your-domain>

To use a certificate from a public or internal certificate authority instead (for example one issued by Let's Encrypt for <your-domain>), copy it over the generated pair and reload nginx (running openproject-set-hostname again replaces it with a self signed one):

sudo install -m 0644 <your-domain>.crt /etc/ssl/openproject/openproject.crt
sudo install -m 0600 <your-domain>.key /etc/ssl/openproject/openproject.key
sudo nginx -t && sudo systemctl reload nginx

Step 9: Security checks

nginx serves only the application. Without a sign in, pages redirect to the sign in page and the API answers 401, hidden files answer 404, plain HTTP redirects to HTTPS, and a request for a name the instance does not serve gets no answer at all:

H=$(sudo grep '^openproject.url=' /root/openproject-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
for p in / /login /projects /api/v3 /api/v3/users /health_checks/default /.git/config /.env; 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
302  /
200  /login
302  /projects
401  /api/v3
401  /api/v3/users
200  /health_checks/default
404  /.git/config
404  /.env
http:// -> 301
unknown host name -> 000

PostgreSQL listens on the loopback address only:

sudo -u postgres psql -X -tA -c "SHOW listen_addresses"
localhost

The certificate was generated on this instance and names its own addresses:

H=$(sudo grep '^openproject.url=' /root/openproject-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
subject=CN = ec2-<public-ip-dashed>.compute-1.amazonaws.com, O = cloudimg
X509v3 Subject Alternative Name:
    DNS:ec2-<public-ip-dashed>.compute-1.amazonaws.com, IP Address:<public-ip>, IP Address:<private-ip>, IP Address:127.0.0.1, DNS:localhost

None of the services can reach the instance metadata service, so an address a user enters can never reach it:

systemctl show nginx openproject-app openproject-jobs postgresql@16-main openproject-firstboot -p Id -p IPAddressDeny
IPAddressDeny=168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32
Id=nginx.service

IPAddressDeny=168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32
Id=openproject-app.service

IPAddressDeny=168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32
Id=openproject-jobs.service

IPAddressDeny=168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32
Id=postgresql@16-main.service

IPAddressDeny=168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32
Id=openproject-firstboot.service

Step 10: Backup, storage and maintenance

Your projects, work packages, users and settings are in the PostgreSQL database openproject (/var/lib/postgresql/16/main); attachments are under /var/db/openproject/files, and OpenProject's settings and secret key are in /etc/openproject. All of it is on the root volume, so the simplest backup is an EBS snapshot of it. For a consistent copy while OpenProject is running:

sudo -u postgres pg_dump -Fc openproject > <backup-dir>/openproject-$(date +%F).dump
sudo tar -C / -czf <backup-dir>/openproject-files-$(date +%F).tar.gz var/db/openproject etc/openproject

The dump and /etc/openproject hold every password hash and the secret key, so store them as carefully as the instance.

To give attachments more room, enlarge the root volume in the EC2 console (Volumes, Modify); Ubuntu grows the file system on the next boot.

Operating system security updates install automatically. nginx, PostgreSQL and the OpenProject services restart cleanly and keep all of their data.

OpenProject's own signed repository (the 17 release line) stays configured, so a newer OpenProject 17 release arrives through apt too, and sudo apt-get upgrade installs it with everything else. Unattended upgrades never install it. Take a snapshot of the root volume first, then upgrade OpenProject, give the files back the image's ownership (the package's installer makes the whole application tree and its settings the service account's), apply the release's database changes and restart:

sudo apt-get update && sudo apt-get install --only-upgrade openproject
sudo chown -R root:root /opt/openproject
sudo chown -R openproject:openproject /opt/openproject/tmp /var/log/openproject /var/db/openproject
sudo chmod -R o-w /opt/openproject
sudo chown -R root:openproject /etc/openproject
sudo openproject-manage rake db:migrate
sudo systemctl restart openproject-app openproject-jobs

Do not run sudo openproject configure: it is the vendor's interactive installer for a fresh server and would add Apache and memcached alongside the image's nginx. A new major release (OpenProject 18) arrives as a new version of this listing; support can help you move your data to it.

Component Path
OpenProject (with its own Ruby) /opt/openproject
Settings and secret key /etc/openproject/conf.d/00-cloudimg, your own settings in /etc/openproject/conf.d/other
Database PostgreSQL 16 database openproject (/var/lib/postgresql/16/main)
Attachments /var/db/openproject/files
Logs journalctl -u openproject-app -u openproject-jobs, /var/log/openproject, nginx logs in /var/log/nginx
nginx site /etc/nginx/sites-available/openproject, served name in /etc/nginx/openproject-host.conf
Certificate and key /etc/ssl/openproject/openproject.crt, /etc/ssl/openproject/openproject.key
Services openproject-app, openproject-jobs, postgresql@16-main, nginx
Helpers /usr/local/sbin/openproject-set-hostname, openproject-set-admin-password, openproject-manage, openproject-selftest.sh
Credentials /root/openproject-credentials.txt (mode 0600)

Step 11: Security recommendations

  • Allow port 22 from your admin network only, and ports 80 and 443 only from the networks your team works from.
  • Use your own DNS name and a certificate your team's browsers trust (Step 8).
  • Replace the placeholder administrator address and password (Step 5), and give each person their own account with the narrowest role that fits.
  • Turn on two-factor authentication, and disable self registration if you do not use it (Step 7).
  • Use API tokens rather than passwords for scripts, one token per script, and revoke tokens you no longer use.
  • Keep the operating system patched, and snapshot the root volume regularly.

Support and licensing

OpenProject is open source under the GNU General Public License v3.0, by OpenProject GmbH; the licence is in /opt/openproject/LICENSE, and the source of the exact release on the image is listed in /opt/openproject/SOURCE-cloudimg.txt. This image is the Community edition: Enterprise add-ons marked with a badge in the menus need a token from OpenProject GmbH. There is no per user licence fee. The AMI price covers cloudimg's hardening, first boot setup and support.

  • 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.