Deployment guide

OpenProject 17.9.6

Overview

This guide shows you how to launch and use the OpenProject 17.9.6 on Ubuntu 24.04 AMI from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud 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 and 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 you get:

  • 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. It also creates 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 that is 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 that 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, together with the address of the connection itself. OpenProject's failed sign-in log and its lock after repeated wrong passwords therefore 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. An address that 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. 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 that you cannot get.
  • Fully patched. Ubuntu 24.04 LTS is fully patched 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 that is subscribed to the listing, an EC2 key pair, and a VPC subnet with a route to the internet (or a private route that you use for management).
  • A security group that allows TCP 22 (SSH) from your admin network. It must also allow 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 that your team attaches to work packages are stored on the root volume. If you expect many of them, give the instance a larger root volume at launch (Step 1).
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 select your Region, then choose Launch through EC2.

Choose m5.large (or larger for a big team), your key pair and a security group as described above. Under Configure storage, set the root volume to the size your attachments need (for example 50 GiB).

Alternatively, launch 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 first boot has finished, and it needs about one more minute before it answers. Allow four to five minutes in all.

2

Connect to your instance

For OpenProject 17.9.6 on Ubuntu 24.04, the SSH user is ubuntu. Connect with your key pair:

ssh -i <your-key.pem> ubuntu@<public-ip>
3

Check the services

Wait until OpenProject answers. This command 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

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

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

Confirm that 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

Run the image's self-test. It 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
4

Get your URL and password

Print the credentials file. Only root can read it:

sudo cat /root/openproject-credentials.txt

The file contains your sign-in URL and your administrator password:

# OpenProject 17.9.6 on Ubuntu 24.04 by sac
# 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>.
5

Sign in

Open the openproject.url value 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. After you sign in, OpenProject's home page opens with the menu of modules on the left.

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 stand-in value (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 that 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
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.

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 Gantt chart shows the same work packages on a timeline, with their dependencies. Drag a bar to move or stretch it.

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 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 a token, 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
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.

Go to Administration, Emails and notifications, Email notifications. Choose smtp as the delivery method and enter your relay's address, port, user name and password. Set the Emission email address to the address that OpenProject should send from, then 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 only an administrator creates your team's accounts.

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 matching line to /etc/openproject/conf.d/other and restart the services as shown 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, which only root and the openproject service account can read. Use one export NAME="value" line for each setting, and 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-sac as it is. First boot generated its database address, host name and SECRET_KEY_BASE for this instance, and openproject-set-hostname (Step 8) rewrites it. The services refuse to start with the stand-in values that the image ships.

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

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 the packages:

sudo pro attach <your-ubuntu-pro-token>
sudo apt-get install imagemagick tesseract-ocr catdoc
sudo systemctl restart openproject-app openproject-jobs
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 command creates a new self-signed certificate for the name and points nginx and OpenProject at it. That name is the only one OpenProject answers, and it is used for the links in its e-mails. The command also 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
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 that 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

Confirm that PostgreSQL listens on the loopback address only:

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

Confirm that 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 = sac 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

Confirm that none of the services can reach the instance metadata service, so an address that 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
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 that volume. For a consistent copy while OpenProject is running, use these commands:

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

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. A newer OpenProject 17 release therefore arrives through apt too, and sudo apt-get upgrade installs it with everything else. Unattended upgrades never install it.

To upgrade OpenProject, take a snapshot of the root volume first. Then upgrade, restore the image's file 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 it 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.

Where things are on the instance:

  • OpenProject (with its own Ruby): /opt/openproject
  • Settings and secret key: /etc/openproject/conf.d/00-sac, with 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, and nginx logs in /var/log/nginx
  • nginx site: /etc/nginx/sites-available/openproject, with the served name in /etc/nginx/openproject-host.conf
  • Certificate and key: /etc/ssl/openproject/openproject.crt and /etc/ssl/openproject/openproject.key
  • Services: openproject-app, openproject-jobs, postgresql@16-main and nginx
  • Helpers: /usr/local/sbin/openproject-set-hostname, openproject-set-admin-password, openproject-manage and openproject-selftest.sh
  • Credentials: /root/openproject-credentials.txt (mode 0600)
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 initial administrator e-mail 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-sac.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 SecureAnyCloud's hardening, first-boot setup and support.

  • Email: sales@secureanycloud.com
  • Website: https://secureanycloud.com
  • 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.

Deploy on AWS

Launch OpenProject 17.9.6 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.

View on Marketplace

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on AWS