Apache Allura 1.22.1
Overview
Apache Allura is the Apache Software Foundation's open source forge, the software behind SourceForge. Every project gets its own space with a Git repository, a ticket tracker, a wiki, discussion forums, a blog, file releases and an activity feed. Allura also provides fine-grained permissions, merge requests, full-text search and a REST API.
This SecureAnyCloud AMI runs Apache Allura 1.22.1 on Ubuntu 24.04 on Amazon EC2, hardened for use from the first boot. The AMI is one version of the SecureAnyCloud Apache Subversion (SVN) and CI/CD Tools listing on AWS Marketplace. You pick it as the software version when you subscribe and launch.
What you get:
- The current release, verified. Allura 1.22.1 is the official Apache release tarball, checked against the SHA-512 the ASF publishes. It carries the fixes for every Allura security advisory published up to its release, including the critical CVE-2026-118196 that every release up to 1.22.0 is affected by (source: Apache Allura's own 1.22.1 release note), and the earlier CVE-2026-75099, CVE-2026-80180, CVE-2026-80181, CVE-2026-80190, CVE-2026-81270, CVE-2026-92116, CVE-2026-92119 and CVE-2026-92120 among them.
- Python dependencies pinned and patched. Every Python package is pinned by hash at the versions Allura 1.22.1 ships, with anyio raised past its published advisory within Allura's own version range. A
pip-auditof the shipped environment is a build gate. - No MongoDB, no SSPL. Allura speaks the MongoDB protocol. This image gives it FerretDB 2.7.0 (Apache-2.0) on PostgreSQL 17 with the DocumentDB extension instead of MongoDB, so every component is under an open source licence. FerretDB is compiled from its source with a current Go toolchain and patched modules, so the binary carries no known reachable vulnerability.
- Search on a supported Solr. Allura's search runs on Apache Solr 10.1.0, the current Solr release line, with Allura's search schema ported to it.
- Debug mode off. Upstream's sample configuration runs Allura in debug mode, which puts an interactive Python debugger on every error page. This image switches debug mode off.
- A datastore, keys and an administrator of your instance's own. Nothing secret is baked into the image, and there is no database at all until your instance's first boot. First boot creates the instance's own PostgreSQL cluster, its datastore password, Allura's session signing key and the master key for Allura's field-level encryption. It then runs Allura's own setup with exactly one administrator,
admin, with a password generated on your instance. Upstream's demo accounts (with the published passwordfoo) are never created. Secrets never appear on a command line or in a log. - HTTPS from the first boot. nginx serves Allura on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS, and the session cookie is HTTPS-only.
- Fail closed. nginx and Allura do not start until first boot has finished. If first boot cannot complete, the site stays offline rather than open.
- Closed by default. Public registration is off (the administrator creates accounts), and Allura does not call out to check passwords against an online breach list.
- Links from other sites cannot act for you. Every form submission, every other request that changes something, and the log-out only work when they come from your site itself. Allura's sign-in and API pages cannot be pulled into another page as an image or a frame.
- A rate-limited sign-in. nginx allows 10 attempts a minute from one address at every sign-in, password recovery and OAuth endpoint (after a burst of 10). It uses the address of the connection, never a header a client sends.
- The real host and client address. nginx hands Allura the host name you configure and nothing a request claims, removes
X-Forwarded-Forand every other forwarding header a client sends, and Allura records the address of the connection. - Backends on loopback only. PostgreSQL has no network listener at all (local socket only), and FerretDB, Solr (with its admin interface switched off) and Allura's own web server listen on
127.0.0.1only. The open ports are 22, 80 and 443. - Every backend asks for a credential. Being on loopback is not treated as being safe. Solr requires a password generated on your instance's first boot (Solr's own BasicAuth). FerretDB requires its own password, and its debug endpoint is switched off. PostgreSQL accepts local socket logins only.
- Allura cannot be turned against your network. Allura fetches addresses that its users type in: webhooks, project importers, repository imports and video embeds. Every one of those requests is refused if it is aimed at this instance's own services, a private network, a link-local address or the instance metadata service, however the address is written. The check runs on the address actually connected to, after the DNS lookup and again at every redirect. A kernel-level block backs it up for every program Allura runs, Git included. Git may only use the
https,http,gitand local transports, without following redirects. - Hardened defaults. Allura, Solr, FerretDB and PostgreSQL each run as their own unprivileged user in a systemd sandbox. All program files belong to root and are read-only to the services, and nothing in Allura's data folders (repositories and their hooks, caches) can run as a program. Every service is blocked from the instance metadata service at the kernel level. The AMI requires IMDSv2, and requests for a host name the instance does not serve are dropped.
- Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
What is on the image: Apache Allura 1.22.1, FerretDB 2.7.0, PostgreSQL 17 with DocumentDB 0.107.0, Apache Solr 10.1.0 on OpenJDK 21, Python 3.12, Git, 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
You need:
- 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 (administrator SSH), TCP 443 (Allura) and TCP 80 (redirects to HTTPS) from the networks that should reach them. Restrict port 22 to your own networks.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick Apache Allura 1.22.1 on Ubuntu 24.04 as the software version and choose your Region. Then choose Launch through EC2.
Choose m5.large, your key pair and a security group as described above. Allura, Solr and the database share the instance, and 8 GiB of memory leaves room to grow. The root volume holds the database, the search index and your repositories, so size it for your projects.
To launch with the AWS CLI instead, 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=allura}]'Connect to your instance
Version SSH user
Apache Allura 1.22.1 on Ubuntu 24.04 ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
First boot takes about a minute. It creates the database, starts Solr and runs Allura's setup. When it finishes, the six services and the first-boot unit are active:
systemctl is-active allura-firstboot postgresql@17-main ferretdb solr allura-web allura-taskd nginxactive active active active active active activeOnly SSH and nginx listen on the network. FerretDB, Solr and Allura's web server listen on 127.0.0.1 (Solr's second port is its local stop port), and PostgreSQL has no TCP port at all:
sudo ss -tlnp | awk 'NR==1 || /nginx|sshd|gunicorn|ferretdb|java|postgres/' | awk '{print $1, $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g'State Local Peer LISTEN 127.0.0.1:27017 users:(("ferretdb")) LISTEN 127.0.0.1:8080 users:(("gunicorn: LISTEN 0.0.0.0:443 users:(("nginx"),("nginx"),("nginx")) LISTEN 0.0.0.0:22 users:(("sshd"),("systemd")) LISTEN 0.0.0.0:80 users:(("nginx"),("nginx"),("nginx")) LISTEN [::ffff:127.0.0.1]:7983 users:(("java")) LISTEN [::ffff:127.0.0.1]:8983 users:(("java")) LISTEN [::]:443 users:(("nginx"),("nginx"),("nginx")) LISTEN [::]:22 users:(("sshd"),("systemd")) LISTEN [::]:80 users:(("nginx"),("nginx"),("nginx"))The versions on the image:
grep -m1 '^Version' /opt/allura/CHANGES /usr/local/bin/ferretdb --version | head -1 sudo -u postgres psql -tAc 'show server_version' ls /opt/solr-10.1.0/server/solr-webapp/webapp/WEB-INF/lib/ | grep -m1 '^solr-core-' echo "MongoDB packages installed: $(dpkg -l | grep -Eic 'mongodb-org|percona-server-mongodb' || true)"Version 1.22.1 (November 2026) version: v2.7.0 17.11 (Ubuntu 17.11-1.pgdg24.04+2) solr-core-10.1.0.jar MongoDB packages installed: 0Get your sign-in details
The credentials file holds the address Allura is served as (your instance's public DNS name by default). It also holds the administrator's user name and password, which were generated on this instance:
sudo grep -E '^ALLURA_(URL|ADMIN_USER)=' /root/allura-credentials.txt
sudo grep -c '^ALLURA_ADMIN_PASSWORD=[A-Za-z0-9]\{24\}$' /root/allura-credentials.txtALLURA_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ ALLURA_ADMIN_USER=admin 1To see the password itself, run sudo cat /root/allura-credentials.txt. Then check the sign-in end to end. The administrator signs in through the real form, a wrong password is refused, and port 80 redirects to HTTPS:
sudo allura-cred-roundtripOK https 301Sign in from your browser
Open ALLURA_URL in your browser. The certificate is self-signed and was generated on your instance, so your browser warns you once. Compare the certificate's SHA-256 fingerprint with the one on the instance (sudo openssl x509 -in /etc/nginx/ssl/allura.crt -noout -fingerprint -sha256) and continue. Alternatively, install a certificate from your own certificate authority (Step 10). A fresh forge shows the projects home page.
Choose Log In and sign in with admin and the password from Step 4.
You land on your dashboard. It lists your projects, tickets, merge requests and recent activity, which are empty on a new forge.
Create a project
Choose Add Project (or open /p/add_project). Give the project a name and a short URL name (letters, digits and dashes, at most 15 characters). Keep the tools you want and choose Create.
Allura's background worker sets the tools up in a few seconds. The project has a summary page, a wiki, a Git repository (Code), tickets, discussion forums and an admin section.
Wiki, tickets and search
Open Wiki and edit the Home page. Allura's Markdown editor has formatting buttons and a preview, which the server renders with Allura's own HTML sanitising.
Saving renders the page and keeps every revision.
Tickets is the project's issue tracker. Every ticket has a status, owner, milestone, labels and a threaded discussion.
Allura's task worker indexes wiki pages, tickets, forum posts and commits into Solr a few seconds after you save them. The project's Search then finds them.
Your Git repository
Each project's Code tool is a Git repository that Allura creates under /var/lib/allura/scm/git. In the browser you can browse files, commits and branches, compare and merge branches with merge requests, or fork a repository into another project.
The repository folders belong to the allura service user. Allura does not include a Git server for pushes from workstations, and this image does not add one. Nobody can push a repository, or plant a hook in one, over the network.
You can import an existing repository with Admin, then Import. Allura clones it as the service user, without copying any hooks.
To push from your workstation as the instance administrator, push over your SSH login and run Git's receiving side as the allura user. Replace the values in angle brackets. The repository path is /var/lib/allura/scm/git/p/<project>/<tool>.git:
git remote add allura ssh://ubuntu@<instance-dns-name>/var/lib/allura/scm/git/p/webapp/code.git
git push --receive-pack='sudo -n -u allura git-receive-pack' allura mainAllura's own post-receive hook then refreshes the repository, so the commits show up in the browser. On the instance, allura owns every repository and its hooks:
sudo find /var/lib/allura/scm/git -mindepth 3 -maxdepth 3 -name '*.git' -printf '%u:%g %p\n'
sudo find /var/lib/allura/scm/git -path '*.git/hooks/post-receive' -printf '%u %m %p\n'allura:allura /var/lib/allura/scm/git/p/webapp/code.gitSecurity checks
These checks confirm that port 80 sends browsers to HTTPS and that a visitor cannot register. They also confirm that nginx closes the connection for a host name the instance does not serve (000 means no answer) and that Allura's debugger is not reachable:
H=$(sudo sed -n 's#^ALLURA_URL=https://\([^/]*\)/.*#\1#p' /root/allura-credentials.txt)
curl -s -o /dev/null -D - --resolve "$H:80:127.0.0.1" "http://$H/" | tr -d '\r' | awk 'NR==1{print "port 80:", $2} tolower($1)=="location:"{print " to:", ($2 == "https://'"$H"'/" ? "https://<this host>/" : $2)}'
curl -sk -o /dev/null -w 'sign in page: %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/auth/"
curl -sk -o /dev/null -w 'registration page: %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/auth/create_account"
curl -sk -o /dev/null -w 'debugger: %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/?__debugger__=yes&cmd=resource&f=style.css"
curl -s -o /dev/null -w 'unknown host name: %{http_code}\n' -H 'Host: example.com' http://127.0.0.1/ || trueport 80: 301 to: https://<this host>/ sign in page: 200 registration page: 404 debugger: 302 unknown host name: 000nginx refuses a form submitted from another site before it reaches Allura. It also refuses a sign-in page requested as an image or a frame inside another page:
H=$(sudo sed -n 's#^ALLURA_URL=https://\([^/]*\)/.*#\1#p' /root/allura-credentials.txt)
curl -sk --resolve "$H:443:127.0.0.1" -H 'Origin: https://example.com' -d 'username=x&password=y' "https://$H/auth/do_login"
curl -sk --resolve "$H:443:127.0.0.1" -H 'Sec-Fetch-Site: cross-site' -X DELETE "https://$H/p/webapp/wiki/Home/"
curl -sk --resolve "$H:443:127.0.0.1" -H 'Sec-Fetch-Dest: iframe' "https://$H/auth/"sac: cross-site state-changing request refused sac: cross-site state-changing request refused sac: /auth/ or /rest/ requested as a subresource refusedScripts that use Allura's REST API with an OAuth bearer token in the Authorization header, and no browser cookie, are not affected.
These are the settings behind the checks, in Allura's configuration file:
sudo grep -E '^(set )?debug = |^(base_url|domain|session\.secure|auth\.allow_user_registration|ip_address_header) = ' /opt/allura/Allura/sac.ini | sed -E 's#(base_url = https://|domain = ).*#\1<this host>#'debug = false set debug = false ip_address_header = X-Real-IP domain = <this host> base_url = https://<this host> session.secure = true auth.allow_user_registration = falseThe datastore, the search engine and the web server are reachable on loopback only, and PostgreSQL accepts local socket logins only. FerretDB requires a login and its debug endpoint is off. Solr answers 401 to any request without the password Allura uses:
sudo -u postgres psql -tAc "show listen_addresses" | sed 's/^$/(no TCP listener)/'
sudo grep -vE '^\s*(#|$)' /etc/postgresql/17/main/pg_hba.conf
sudo grep -E '^FERRETDB_(LISTEN_ADDR|AUTH|DEBUG_ADDR)=' /etc/ferretdb/ferretdb.env systemctl show -p ExecStart --value ferretdb | grep -o 'argv\[\]=[^;]*' grep -E '^SOLR_(HOST_BIND|UI_ENABLED)=' /etc/default/solr.in.sh /opt/allura-venv/bin/python -c 'import pymongo; c = pymongo.MongoClient("mongodb://127.0.0.1:27017/", serverSelectionTimeoutMS=5000) try: c.admin.command("listDatabases"); print("anonymous read: allowed") except Exception as e: print("anonymous read:", "refused" if "requires authentication" in str(e) else e)' curl -s -o /dev/null -w 'Solr without a password: %{http_code}\n' 'http://127.0.0.1:8983/solr/allura/select?q=*:*'
sudo sed -n 's/^solr\.pass = \(.*\)/user = "allura:\1"/p' /opt/allura/Allura/sac.ini | curl -s -o /dev/null -K - -w "Solr with Allura's password: %{http_code}\n" 'http://127.0.0.1:8983/solr/allura/admin/ping'(no TCP listener) local all postgres peer local all all peer map=sac FERRETDB_LISTEN_ADDR=127.0.0.1:27017 FERRETDB_AUTH=true argv[]=/usr/local/bin/ferretdb --debug-addr= SOLR_HOST_BIND="127.0.0.1" SOLR_UI_ENABLED="false" anonymous read: refused Solr without a password: 401 Solr with Allura's password: 200Allura's own Python refuses to connect to the metadata service, to this instance's backends and to private networks, while a public address works. The same check applies to webhooks, importers and embeds:
/opt/allura-venv/bin/python -c ' import urllib.request for u in ("http://169.254.169.254/latest/meta-data/", "http://127.0.0.1:8983/solr/", "http://2130706433:27017/", "http://[::ffff:10.0.0.1]/", "https://www.apache.org/"): try: print(u, "->", urllib.request.urlopen(u, timeout=10).status) except Exception as e: print(u, "-> refused" if "sac egress guard" in str(e) else "-> %s" % e)'http://169.254.169.254/latest/meta-data/ -> refused http://127.0.0.1:8983/solr/ -> refused http://2130706433:27017/ -> refused http://[::ffff:10.0.0.1]/ -> refused https://www.apache.org/ -> 200Every service runs as its own user and is blocked from the instance metadata service. Allura's two services are also blocked from private and link-local networks, which is why their list is longer:
for u in allura-web allura-taskd solr ferretdb postgresql@17-main nginx; do printf '%s: %s %s\n' "$u" "$(systemctl show -p User --value $u)" "$(systemctl show -p IPAddressDeny --value $u)"; doneallura-web: allura 192.168.0.0/16 10.0.0.0/8 198.18.0.0/15 169.254.0.0/16 192.0.0.0/24 ::/128 224.0.0.0/3 fe80::/10 fec0::/10 172.16.0.0/12 168.63.129.16/32 100.64.0.0/10 ::1/128 127.0.0.0/8 0.0.0.0/8 64:ff9b:1::/48 fc00::/7 ff00::/8 allura-taskd: allura 172.16.0.0/12 ::1/128 fe80::/10 100.64.0.0/10 0.0.0.0/8 fc00::/7 64:ff9b:1::/48 192.168.0.0/16 198.18.0.0/15 168.63.129.16/32 ::/128 224.0.0.0/3 10.0.0.0/8 192.0.0.0/24 127.0.0.0/8 ff00::/8 169.254.0.0/16 fec0::/10 solr: solr 169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 ferretdb: ferretdb 169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 postgresql@17-main: 169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 nginx: 169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32The certificate was generated on this instance and names its own addresses:
H=$(sudo sed -n 's#^ALLURA_URL=https://\([^/]*\)/.*#\1#p' /root/allura-credentials.txt)
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -ext basicConstraints,extendedKeyUsage | sed -E 's/^ +//'X509v3 Basic Constraints: critical CA:FALSE X509v3 Extended Key Usage: TLS Web Server AuthenticationYour own DNS name and certificate
Point a DNS record at the instance, then set the name Allura is served as. The command mints a new self-signed certificate for the name. It updates nginx, Allura's base_url and domain (so links and notification mails use the new name) and the URL in /root/allura-credentials.txt. It then restarts Allura:
sudo allura-set-hostname forge.example.comTo use a certificate from your certificate authority instead, replace /etc/nginx/ssl/allura.crt and /etc/nginx/ssl/allura.key (keep the key 0600 root) and run sudo systemctl reload nginx.
Behind a load balancer or proxy that terminates TLS, forward to port 443 of the instance and keep the Host header as the name above.
Accounts, e-mail, passwords and backups
- Accounts. Public registration is off. To let people register themselves, set
auth.allow_user_registration = truein/opt/allura/Allura/sac.iniand runsudo systemctl restart allura-web allura-taskd. Otherwise, create accounts for them asadminunder Site Admin. - E-mail. Allura sends notifications and password resets to
localhost:25, and the image has no mail server. Pointsmtp_server,smtp_port(andsmtp_tls,smtp_user,smtp_passwordif needed) insac.iniat your mail relay, such as Amazon SES. Then restartallura-webandallura-taskd. - The admin password.
sudo allura-set-passwordsets a new random password foradminand writes it to/root/allura-credentials.txt. Runsudo allura-set-password <user>for another account, and it prints the new password. - Backups. Allura's data is the PostgreSQL cluster (
/var/lib/allura/pg17), the repositories (/var/lib/allura/scm) and/opt/allura/Allura/sac.ini. That configuration file holds the field-level encryption master key. Without the key, Allura's encrypted fields (e-mail addresses and other personal data) cannot be read. Snapshot the EBS volume, or stopallura-web allura-taskd ferretdband back up those paths. The Solr index (/var/lib/solr/data) can be rebuilt from the datastore. - Webhooks and imports from your private network. Allura refuses to send webhooks to, or import from, private addresses. To allow one internal network (for example
10.0.5.0/24), runsudo systemctl edit allura-taskdandsudo systemctl edit allura-web, and add these lines to each. Then seturlopen_allow_internal_hostnames = trueinsac.iniand restart both services. This instance's own services, link-local addresses and the metadata service stay blocked whatever you allow.
text [Service] Environment=SAC_EGRESS_ALLOW=10.0.5.0/24 IPAddressAllow=10.0.5.0/24
- Upgrades. Ubuntu security updates install automatically. For a new Allura release, follow the upgrade notes in
/opt/allura/CHANGES.
Server components
Component Version Listens on Runs as
Apache Allura (gunicorn) 1.22.1 127.0.0.1:8080 allura
Allura task worker 1.22.1 - allura
FerretDB 2.7.0 127.0.0.1:27017 ferretdb
PostgreSQL + DocumentDB 17 + 0.107.0 local socket only postgres
Apache Solr 10.1.0 127.0.0.1:8983 solr
nginx 1.24 0.0.0.0:80, 0.0.0.0:443 www-data
Files: the application in /opt/allura and /opt/allura-venv (root's, read only), the configuration in /opt/allura/Allura/sac.ini (0640 root:allura), the data in /var/lib/allura, Allura's logs in /var/log/allura and journalctl -u allura-web -u allura-taskd.
Security recommendations
- Keep port 22 open to your own networks only, and use your own certificate (Step 10) before inviting users.
- Keep the backends on loopback: never open 8080, 8983 or 27017 in your security group. Solr's password is in
sac.ini; keep that file0640 root:allura.
- Back up
sac.initogether with your data (Step 11).
- If you open registration, review new accounts under Site Admin and consider requiring e-mail confirmation (configure e-mail first).
Support and licensing
Apache Allura, Apache Solr and FerretDB are licensed under the Apache License 2.0, PostgreSQL under the PostgreSQL Licence and DocumentDB under the MIT licence. SecureAnyCloud provides the image, its hardening and support; Allura itself is developed by the Apache Software Foundation. For help with this image, contact SecureAnyCloud support through the AWS Marketplace listing.
Deploy on AWS
Launch Apache Allura 1.22.1 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