Erugo 0.2.15
Overview
Erugo is a self-hosted file sharing and file transfer platform. You upload files or whole folders in the browser, and Erugo gives you a short link to send. Recipients download everything in one go, without an account.
This guide covers the Erugo 0.2.15 on Ubuntu 24.04 AMI from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud file sharing and sync listing on AWS Marketplace. You select it as the software version when you subscribe and launch.
Erugo shares expire on a date you choose, can be password protected or limited to a number of downloads, and can be emailed to recipients directly. Large uploads are resumable, so a dropped connection picks up where it left off. A "reverse share" request lets someone outside your organization upload files to you.
Version 0.2.15 fixes the critical upload flaw GHSA-336w-hgpq-6369 (remote code execution, versions 0.2.14 and earlier).
A stock Erugo install creates its first administrator through a web setup page that stays open until somebody uses it, so the first visitor to a new server becomes its administrator. The SecureAnyCloud image closes that gap and adds more.
What you get:
- No setup page, no default login. The image ships with the administrator account already in place and its setup page sealed. On first boot, the instance generates its own administrator password, Laravel application key and token signing secret. It writes the password to
/root/erugo-credentials.txt, readable by root only. Nothing secret is baked into the image. - HTTPS from the first boot. nginx serves Erugo on port 443 with a certificate generated on your instance. Port 80 only redirects to HTTPS, and a request for a host name the instance does not serve gets no answer.
- Share links that name your server, not the visitor's request. The address in share links, emails and password reset links comes from the instance's own configuration (its public address, or the DNS name you set), never from a header a client sends.
- Uploads that cannot run. Shared files are served only as downloads (with
Content-Disposition: attachmentandnosniff). Uploads never execute as code, only Erugo's own entry point runs PHP, and the application code is read-only to the web server. - Bounded uploads. A share can hold up to 2 GB (Erugo's own default, enforced again by the upload service). The upload service never serves files back without going through Erugo's share checks.
- Brute-force throttling. Sign-in, token refresh and password reset are rate limited per client address, and a wrong password gets a plain "Invalid credentials" answer.
- Hardened defaults. The services cannot reach the instance metadata service, and the AMI requires IMDSv2. The upload service and its internal callback listen on
127.0.0.1only, the application trusts forwarded headers from the local proxy only, and the PHP dependencies are updated to their latest security releases. - Your files on their own volume. The application, its database and every upload live on a separate 32 GiB EBS volume mounted at
/var/www, which you can grow and snapshot on its own. - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
- 24/7 SecureAnyCloud support.
What is on the image: Erugo 0.2.15 (from the checksum-verified release), the resumable upload service tusd 2.10.1, nginx 1.24, PHP 8.3 with PHP-FPM, SQLite, 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.
- A security group that allows TCP 443 (Erugo) and TCP 80 (redirects to HTTPS) from the people who will upload and download, and TCP 22 (SSH) from your own networks only.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick Erugo 0.2.15 on Ubuntu 24.04 as the software version, choose your Region, then choose Launch through EC2.
Choose m5.large, your key pair and a security group as described above. Keep the second EBS volume, which holds Erugo and every file you share. Grow it at launch if you plan to share a lot.
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> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=erugo}]'Connect to your instance
Version SSH user
Erugo 0.2.15 on Ubuntu 24.04 ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services, ports and data volume
First boot takes a few seconds. After that, nginx, PHP-FPM, the upload service (erugo-tusd), the queue worker that packages shares and sends mail (erugo-queue), the first-boot unit and the scheduler are all active:
systemctl is-active nginx php8.3-fpm erugo-tusd erugo-queue erugo-firstboot erugo-scheduler.timeractive active active active active activenginx is the only public listener. The upload service (8080) and Erugo's internal upload callback (8081) listen on loopback only. Confirm it:
sudo ss -tlnp | awk 'NR==1 || /nginx|sshd|tusd/' | awk '{print $1, $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g'State Local Peer LISTEN 0.0.0.0:443 users:(("nginx"),("nginx"),("nginx")) LISTEN 0.0.0.0:80 users:(("nginx"),("nginx"),("nginx")) LISTEN 0.0.0.0:22 users:(("sshd"),("systemd")) LISTEN 127.0.0.1:8081 users:(("nginx"),("nginx"),("nginx")) LISTEN 127.0.0.1:8080 users:(("tusd")) LISTEN [::]:443 users:(("nginx"),("nginx"),("nginx")) LISTEN [::]:80 users:(("nginx"),("nginx"),("nginx")) LISTEN [::]:22 users:(("sshd"),("systemd"))Erugo, its database and your files are on the separate data volume. Confirm the mount:
findmnt -no SOURCE,TARGET,FSTYPE /var/www df -h --output=size,avail,target /var/www/dev/nvme1n1 /var/www ext4 Size Avail Mounted on 32G 30G /var/wwwGet your URL and password
The address and the administrator password generated on this instance are in a root-only file. Read it with sudo:
sudo cat /root/erugo-credentials.txt# Erugo 0.2.15 - generated on first boot by erugo-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret. ERUGO_URL=https://<public-ip>/ erugo.url=https://<public-ip>/ erugo.admin.user=admin@erugo.local erugo.admin.pass=<24 letters and digits>
# Sign in at the URL above with the e-mail address and password. The certificate is self signed (minted on this
# instance), so the browser warns once. Port 80 redirects to https.
# Change the name Erugo is served as (share links use it):
sudo erugo-set-hostname <your-dns-name>
# Largest upload: 2 GB per share (Erugo setting "Max share size" + tusd -max-size; see the user guide).
# User guide: https://secureanycloud.com/stacks/erugo-0-2-15/To print just the address and the sign-in email, without the password, run:
sudo grep -E '^(erugo\.url|erugo\.admin\.user)=' /root/erugo-credentials.txterugo.url=https://<public-ip>/ erugo.admin.user=admin@erugo.localSign in
Open erugo.url in your browser. The certificate is self-signed and generated on your instance, so accept the browser warning once, or use your own name and certificate (Step 10).
Sign in with admin@erugo.local and erugo.admin.pass.
After you sign in, open My Account from the settings (gear) button and change the email address to your own, so password reset and notification emails reach you.
Share files
Click Add Files or Add Folders and pick what you want to send. Give the share a name and, optionally, a message for the recipients.
Click Add Recipient to have Erugo email the link for you (once SMTP is set up in Step 9). Without recipients, Erugo simply gives you the link.
The line under the buttons shows the size so far against the 2 GB limit and when the share expires. Click (change) to pick another expiry. The padlock button sets a password on the share.
Click Upload. The files go up in resumable chunks, and when they finish, Erugo shows the share link to copy.
The recipient opens the link, sees the files, your message and when the share expires, and downloads everything with one click. Several files arrive as one ZIP, packaged by the queue worker.
Under the gear button, My Shares lists your shares with their download counts and dates. From there you can expire a share at once or extend it.
Check the appliance
The image ships a self test that exercises the whole path over HTTPS. The administrator signs in, uploads a random file through the resumable upload service and shares it. The test then waits for the queue worker to package the share, downloads it through the public link byte for byte, and expires and removes the test share.
The self test also confirms that wrong and blank passwords, a second administrator through the setup page, and anonymous shares or uploads are all refused. Run it:
sudo /usr/local/sbin/erugo-cred-roundtrip.shOK per-instance admin signs in (JWT) and round-trips a 177064-byte payload through tus, a share and the queue worker (test share expired and pruned); weak/blank passwords, a second admin, anonymous shares and anonymous uploads refusedSecurity checks
These checks confirm the following:
- Plain HTTP redirects to HTTPS on the configured name.
- A request for a host name the instance does not serve gets no answer.
- Erugo's internal upload callback cannot be reached from the network.
- A wrong password is refused.
- The first-run setup page refuses a second administrator.
- An upload bigger than the limit is refused before any data is sent.
H=$(sudo sed -nE 's#^erugo\.url=https://([^/]+)/$#\1#p' /root/erugo-credentials.txt)
curl -s -o /dev/null -w 'plain HTTP: %{http_code} -> %{redirect_url}\n' --connect-to "$H:80:127.0.0.1:80" "http://$H/"
curl -s -o /dev/null -w 'unknown host name: %{http_code}\n' -H 'Host: evil.example' http://127.0.0.1/ || true
curl -sk -o /dev/null -w 'upload callback from the network: %{http_code}\n' --connect-to "$H:443:127.0.0.1:443" -X POST "https://$H/api/tusd-hooks"
curl -sk -w ' %{http_code}\n' --connect-to "$H:443:127.0.0.1:443" -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{"email":"admin@erugo.local","password":"password"}' "https://$H/api/auth/login"
curl -sk -w ' %{http_code}\n' --connect-to "$H:443:127.0.0.1:443" -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{"name":"x","email":"x@example.com","password":"Intruder12345","password_confirmation":"Intruder12345"}' "https://$H/api/setup"
curl -sk -o /dev/null -w 'a 3 GiB upload: %{http_code}\n' --connect-to "$H:443:127.0.0.1:443" -X POST -H 'Tus-Resumable: 1.0.0' -H 'Upload-Length: 3221225472' "https://$H/files/"plain HTTP: 301 -> https://<public-ip>/ unknown host name: 000 upload callback from the network: 404 {"status":"error","message":"Invalid credentials"} 401 {"status":"error","message":"First user already created"} 404 a 3 GiB upload: 413The web server, PHP, the upload service and the queue worker cannot reach the instance metadata service, so a URL that Erugo is asked to fetch, such as a sign-in provider's address, cannot be pointed at it. The secrets are readable by root only, plus the web server group for the application settings:
systemctl show nginx php8.3-fpm erugo-tusd erugo-queue -p Id -p IPAddressDeny
sudo stat -c '%a %U:%G %n' /root/erugo-credentials.txt /var/www/erugo/.env /etc/ssl/erugo/erugo.keyIPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 Id=nginx.service IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 Id=php8.3-fpm.service IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 Id=erugo-tusd.service IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 Id=erugo-queue.service 600 root:root /root/erugo-credentials.txt 640 root:www-data /var/www/erugo/.env 600 root:root /etc/ssl/erugo/erugo.keyThe certificate is generated on this instance and names its own addresses:
H=$(sudo sed -nE 's#^erugo\.url=https://([^/]+)/$#\1#p' /root/erugo-credentials.txt)
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltNamesubject=CN = <public-ip>, O = sac X509v3 Subject Alternative Name: IP Address:<public-ip>, DNS:ec2-<public-ip-dashed>.compute-1.amazonaws.com, IP Address:<private-ip>, DNS:ip-<private-ip-dashed>.ec2.internal, IP Address:127.0.0.1, DNS:localhostSettings, e-mail and the upload limit
Configure everything else in the browser under the gear button:
- System settings holds the application name, the Application URL used in emails, share defaults and notifications. The image keeps the Application URL equal to the configured name, and
erugo-set-hostnamein Step 10 updates it. - SMTP lets Erugo email share links and password resets.
- Auth enables sign-in with an OpenID Connect provider such as Authentik or Microsoft Entra ID.
- Database Backups are daily.
- Users adds accounts for your colleagues.
- Branding & UI sets your logo, colors and backgrounds.
Self-registration is off, so only accounts an administrator creates can upload.
Background videos. You can upload an MP4 or WebM video as a background under Branding & UI, and it plays as usual. The image does not include ffmpeg, so the backgrounds list shows no preview thumbnail for a video (images get one as normal). To get video previews, install ffmpeg yourself with sudo apt-get install ffmpeg. It comes from Ubuntu's community-maintained universe archive.
Upload limit. A share can hold up to 2 GB. Erugo's Max Share Size setting (System settings > Shares) and the upload service's own cap agree on this value. These are the values on this instance:
grep -o -- '-max-size [0-9]*' /etc/systemd/system/erugo-tusd.service echo "SELECT key||'='||value FROM settings WHERE key IN ('max_share_size','max_share_size_unit');" | sudo -u www-data sqlite3 /var/www/erugo/storage/database/database.sqlite-max-size 2147483648 max_share_size=2 max_share_size_unit=GBTo allow bigger shares, raise Max Share Size in the browser. Then raise the upload service's cap to match, in bytes (the example below uses 10 GiB). Make sure the data volume has room (Step 11):
sudo sed -i 's/-max-size [0-9]*/-max-size 10737418240/' /etc/systemd/system/erugo-tusd.service
sudo systemctl daemon-reload && sudo systemctl restart erugo-tusdYour own DNS name and certificate
Point a DNS record at the instance, then set the name Erugo is served as. This creates a new self-signed certificate for the name and updates nginx, the address in share links and emails, and the URL in /root/erugo-credentials.txt. The name persists across reboots.
sudo erugo-set-hostname <your-domain>To use a certificate from your own certificate authority instead, copy it over the generated pair and reload nginx. Running erugo-set-hostname again replaces it with a self-signed certificate.
sudo install -m 0644 <your-domain>.crt /etc/ssl/erugo/erugo.crt
sudo install -m 0600 <your-domain>.key /etc/ssl/erugo/erugo.key
sudo nginx -t && sudo systemctl reload nginxGrow the data volume
Erugo, its SQLite database and every shared file live on the EBS volume mounted at /var/www. To make room, grow that volume in the EC2 console (Volumes > Modify volume). Then grow the file system online, with no restart:
sudo resize2fs "$(findmnt -no SOURCE /var/www)"Snapshot the volume to back up Erugo and its files together. Erugo also writes a daily copy of its database to /var/www/erugo/storage/app/backups (kept for 7 days).
Server components
Component Path
Erugo 0.2.15 /var/www/erugo (on the /var/www volume; code read only to the web server)
Database (SQLite) /var/www/erugo/storage/database/database.sqlite
Uploads in progress and shared files /var/www/erugo/storage/app/uploads, /var/www/erugo/storage/app/shares
Application settings and keys /var/www/erugo/.env (root:www-data, 0640)
PHP dependencies shipped /etc/sac/erugo-php-dependencies.txt
Services nginx.service, php8.3-fpm.service, erugo-tusd.service, erugo-queue.service, erugo-scheduler.timer
nginx site /etc/nginx/sites-available/sac-erugo
Certificate and key /etc/ssl/erugo/
First boot script /usr/local/sbin/erugo-firstboot.sh
Host name helper /usr/local/sbin/erugo-set-hostname
Self test /usr/local/sbin/erugo-cred-roundtrip.sh
Credentials /root/erugo-credentials.txt (mode 0600)
Licence /var/www/erugo/LICENSE
Security recommendations
- Allow port 22 in the security group from your own networks only. Ports 80 and 443 must be open to everyone who uploads or downloads.
- Change the administrator email to your own (Step 5) and keep the password private. If it may have leaked, change it under My Account.
- Use your own DNS name and a certificate your browsers trust (Step 10), so recipients are not taught to click through certificate warnings.
- Set an expiry on every share and a password on sensitive ones. Expire shares you no longer need from My Shares.
- Keep the operating system patched. Unattended security upgrades are on, and
sudo apt-get update && sudo apt-get upgradeapplies everything else.
Support and licensing
Erugo is free software under the MIT license (Copyright (c) 2025 Dean Ward), and a copy is at /var/www/erugo/LICENSE. tusd is also MIT licensed. There is no per-user or per-CPU license 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
Deploy on AWS
Launch Erugo 0.2.15 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