G2
Storage AWS

Gokapi 2.2.4 on AWS User Guide

| Product: Gokapi 2.2.4 on Ubuntu 24.04 on AWS

Overview

This guide covers launching and using the Gokapi 2.2.4 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg File Sharing and Sync listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.

Gokapi is a lightweight, self hosted file sharing server. You upload files in its web interface (or through its API) and get a share link for each one, with an optional expiry date, download limit and password. Images can also be shared as hotlinks for embedding. File Requests turn it around: you create a request and send its link to someone who then uploads files to you. Your files stay on your own instance.

The cloudimg image adds:

  • No setup wizard, ever. Upstream Gokapi opens an unauthenticated setup page on every network interface whenever it has no configuration, so the first visitor could take it over. This image never runs that wizard: the first boot writes Gokapi's configuration itself and creates the administrator, and the service refuses to start without that configuration.
  • Passwords unique to your instance. The first boot generates the Gokapi administrator password, a separate password for an extra HTTP Basic Auth layer in front of the administration pages and the API, and the password salts, and writes the two passwords to /root/gokapi-credentials.txt (readable by root only). Nothing is baked into the image.
  • HTTPS from the first boot. nginx serves Gokapi on port 443 with a certificate generated on your instance; port 80 redirects to HTTPS. Requests for a host name the instance does not serve get no answer. Share links use the configured host name, never one taken from a request.
  • Shared files are downloaded, not rendered. Every file Gokapi serves is sent with X-Content-Type-Options: nosniff and a sandboxing Content Security Policy, and anything other than a plain image, audio, video or text file (HTML, SVG, XML, JavaScript, PDF and so on) is sent as a download, so nothing an uploader sends can run in your browser next to your admin session.
  • Built from source with a current Go. The upstream 2.2.4 binary was built with Go 1.26.1 and its standard library carries dozens of security fixes released since. This image compiles Gokapi 2.2.4 from its source with Go 1.27.3 and the fixed releases of golang.org/x/crypto, golang.org/x/image and go-jose; the build record is in /usr/share/doc/gokapi/BUILD-PROVENANCE.txt.
  • Hardened defaults. Gokapi listens on 127.0.0.1 only and runs as its own unprivileged user under a locked down systemd unit. Gokapi and nginx are blocked from the instance metadata service and the AMI requires IMDSv2. The client address Gokapi sees (it rate limits logins) comes from the connection, never from a header a client can forge. A browser request that changes something and comes from another web site is refused.
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.

What is on the image: Gokapi 2.2.4 (/usr/local/bin/gokapi), nginx, SQLite (Gokapi's database is a local file, so there is no database port), 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 443 (the web interface and share links) and TCP 80 (redirects to HTTPS) from the people who will use the service, and TCP 22 (SSH) from your own networks only.

Step 1: Launch the instance

In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Gokapi 2.2.4 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large (Gokapi is light; a smaller type works for a small team), your key pair and a security group as above.

Uploaded files are stored on the root volume under /var/lib/gokapi/data, so give the root volume the space you expect to share (for example 50 GiB instead of the default 8 GiB). The root file system grows to fill the volume on first boot.

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

Step 2: Connect to your instance

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

Step 3: Check the services

First boot takes a few seconds. Then Gokapi, nginx and the first boot unit are active:

systemctl is-active gokapi nginx gokapi-firstboot
active
active
active

nginx is the only web listener; Gokapi itself listens on 127.0.0.1 only:

sudo ss -tlnp | awk 'NR==1 || /nginx|sshd|gokapi/' | 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:22 users:(("sshd"),("systemd"))
LISTEN 0.0.0.0:80 users:(("nginx"),("nginx"),("nginx"))
LISTEN 127.0.0.1:53842 users:(("gokapi"))
LISTEN [::]:443 users:(("nginx"),("nginx"),("nginx"))
LISTEN [::]:22 users:(("sshd"),("systemd"))
LISTEN [::]:80 users:(("nginx"),("nginx"),("nginx"))

The binary reports the release and the Go toolchain it was built with:

/usr/local/bin/gokapi --version | grep -E 'Gokapi v|Builder|Go Version'
Gokapi v2.2.4
Builder: cloudimg source build (go1.27.3)
Go Version: go1.27.3

Step 4: Get your URL and passwords

sudo cat /root/gokapi-credentials.txt

The file holds the address Gokapi is served as (your instance's public IP address by default) and the two passwords generated on this instance:

# Gokapi 2.2.4 - generated on first boot by gokapi-firstboot.service. Unique to this instance; keep it safe.

gokapi.url=https://<public-ip>/
gokapi.admin.url=https://<public-ip>/admin

# 1) HTTP Basic Auth on the admin surface (the browser asks for it first):
gokapi.basicauth.user=admin
gokapi.basicauth.pass=<24 letters and digits>

# 2) Gokapi's own login (the page that follows):
gokapi.admin.user=admin
gokapi.admin.pass=<24 letters and digits>

# Share links (/d?id=..., /downloadFile, /h/...) are public, so recipients need only the link.
# Change the host name:  sudo gokapi-set-host <dns-name>
# Change the Basic Auth password:  sudo htpasswd -B /etc/nginx/gokapi.htpasswd admin   (prompts)
# Change the Gokapi password:  sudo gokapi-set-admin-password   (prompts)

Gokapi's configuration was written by the first boot: internal accounts with the user admin, Gokapi bound to 127.0.0.1, files and the SQLite database under /var/lib/gokapi/data, and share links on your configured host:

sudo jq '{ServerUrl, Port, DatabaseUrl, DataDir, Encryption: .Encryption.Level, Auth: .Authentication.Method, User: .Authentication.Username}' /etc/gokapi/config.json
{
  "ServerUrl": "https://<public-ip>/",
  "Port": "127.0.0.1:53842",
  "DatabaseUrl": "sqlite:///var/lib/gokapi/data/gokapi.sqlite",
  "DataDir": "/var/lib/gokapi/data",
  "Encryption": 0,
  "Auth": 0,
  "User": "admin"
}

Step 5: Sign in

Open gokapi.admin.url in your browser. The certificate is self signed (generated on your instance), so accept the browser warning once, or use your own name and certificate (Step 10). The browser first asks for a user name and password: enter admin and gokapi.basicauth.pass. Gokapi then shows its own login page; sign in as admin with gokapi.admin.pass:

The Gokapi login page with user name and password fields and a Login button

Step 6: Upload and share files

The Upload page takes files by drag and drop, paste or a file picker. Before uploading, set how many downloads a file allows, how many days it is kept and, optionally, a password. Every uploaded file is listed with its remaining downloads, expiry date and share link; URL copies the link, and the share menu offers the hotlink (for images) and other formats:

The Gokapi Upload page with the drop zone, the download limit, expiry and password options, and two uploaded files, q3-report.txt and team-photo.png, each with its ID and URL and share buttons

Anyone with a share link sees the file's download page; no login is needed. The link stops working when its downloads are used up or it expires:

The public Gokapi download page for q3-report.txt showing its size and a Download button

Step 7: File Requests

File Requests let other people upload to you. Create a request with the + button (name, file count and size limits, expiry), then send its link; the person you send it to can upload without an account, and the files appear under the request. Guest uploads go through Gokapi's own per-request key, so the Basic Auth password is not needed for them:

The Gokapi File Requests page with its table of requests and the button to create a new one

Step 8: Use the API

Gokapi has an HTTP API (documented on the API page of your instance) for scripts and its command line uploader. Create an API key on the API page, then call the API with that key in the apikey header and the Basic Auth password, which nginx requires for everything under /api/ except File Request uploads. From your own computer, keep both out of the command line: let curl prompt for the Basic Auth password and read the key header from a file:

printf 'apikey: %s\n' '<your-api-key>' > ~/.gokapi-apikey && chmod 600 ~/.gokapi-apikey
curl -k -u admin -H @"$HOME/.gokapi-apikey" -F "file=@photo.jpg" -F allowedDownloads=5 -F expiryDays=7 \
  "https://<public-ip>/api/files/add"

The response is JSON; FileInfo.UrlDownload is the share link. If you use Gokapi's own command line uploader, which only sends the API key, allow it past the Basic Auth layer from your address only (for example with an nginx satisfy any rule) rather than removing the layer.

Step 9: Check the security model

The image ships a self test that proves the credential model over HTTPS: the administration pages refuse you without the Basic Auth password and with a wrong one, accept the right one; the Gokapi administrator password signs in and a wrong one does not; and the setup wizard is closed:

sudo /usr/local/sbin/gokapi-selftest
OK: Basic Auth 401/401/pass; admin login creates a session, wrong password refused; setup wizard closed (404)

Plain HTTP redirects to HTTPS, the administration pages and the API refuse you without the Basic Auth password, the setup wizard does not exist, a login posted from another web site is refused, and a request for a host name the instance does not serve gets no answer:

H=$(sudo sed -nE 's#^gokapi.url=https://([^/]+)/.*#\1#p' /root/gokapi-credentials.txt)
curl -s -o /dev/null -w 'plain HTTP: %{http_code} -> %{redirect_url}\n' --resolve "$H:80:127.0.0.1" "http://$H/"
curl -sk -o /dev/null -w 'admin page without the Basic Auth password: %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/admin"
curl -sk -o /dev/null -w 'API without the Basic Auth password: %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/api/files/list"
curl -sk -o /dev/null -w 'setup wizard: %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/setup/start"
curl -sk -o /dev/null -w 'login posted from another web site: %{http_code}\n' --resolve "$H:443:127.0.0.1" -H 'Origin: https://evil.example' --data 'username=x&password=y' "https://$H/login"
curl -s -o /dev/null -w 'unknown host name: %{http_code}\n' -H 'Host: evil.example' http://127.0.0.1/ || true
plain HTTP: 301 -> https://<public-ip>/
admin page without the Basic Auth password: 401
API without the Basic Auth password: 401
setup wizard: 404
login posted from another web site: 403
unknown host name: 000

Gokapi and nginx cannot reach the instance metadata service; Gokapi trusts forwarded client addresses from nginx on 127.0.0.1 only, and nginx overwrites them with the address of the connection; the secrets are readable by root (or Gokapi's own user, or nginx for the password hash) only:

systemctl show gokapi nginx -p Id -p IPAddressDeny
systemctl show gokapi -p Environment | tr ' ' '\n' | grep -E 'TRUSTED|DOCKER'
grep -E 'proxy_set_header (Host|X-Real-IP|X-Forwarded-For)' /etc/nginx/gokapi-proxy.conf
sudo stat -c '%a %U:%G %n' /root/gokapi-credentials.txt /etc/gokapi/config.json /etc/nginx/gokapi.htpasswd /etc/nginx/ssl/gokapi.key
IPAddressDeny=fd00:ec2::254/128 169.254.169.254/32 168.63.129.16/32
Id=gokapi.service

IPAddressDeny=fd00:ec2::254/128 169.254.169.254/32 168.63.129.16/32
Id=nginx.service
GOKAPI_TRUSTED_PROXIES=127.0.0.1
GOKAPI_DISABLE_DOCKER_TRUSTED_PROXY=true
proxy_set_header Host $gokapi_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
600 root:root /root/gokapi-credentials.txt
600 gokapi:gokapi /etc/gokapi/config.json
640 root:www-data /etc/nginx/gokapi.htpasswd
600 root:root /etc/nginx/ssl/gokapi.key

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

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

Step 10: Your own DNS name and certificate

Point a DNS record at the instance, then set the name Gokapi is served as. This mints a new self signed certificate for the name, updates nginx, the host in every new share link and the URLs in /root/gokapi-credentials.txt, restarts Gokapi and keeps the name across reboots:

sudo gokapi-set-host <your-domain>

To use a certificate from your own certificate authority instead, copy it over the generated pair and reload nginx (running gokapi-set-host again replaces it with a self signed one):

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

Step 11: Change the passwords

To change the Gokapi administrator password, run the helper on the instance. It prompts for the new password twice (so it never appears on a command line), stores it the way Gokapi does, signs every session out, updates gokapi.admin.pass in /root/gokapi-credentials.txt and restarts Gokapi:

sudo gokapi-set-admin-password

To change the Basic Auth password, set a new one for the admin user (htpasswd prompts for it), then update gokapi.basicauth.pass in /root/gokapi-credentials.txt. nginx uses the new password at once:

sudo htpasswd -B /etc/nginx/gokapi.htpasswd admin

Users you add on the Users page get their own logins; Gokapi asks a user whose password you reset to choose a new one at their next sign in.

Step 12: Store files in S3 or S3 compatible storage

Gokapi can keep uploaded files in an S3 bucket (or any S3 compatible store) instead of on the instance. It needs an access key and secret for the bucket: an EC2 instance role is not used, because Gokapi's S3 client only accepts explicit keys and this image blocks Gokapi from the instance metadata service, where role credentials would come from. Create an IAM user (or a key for your S3 compatible service) limited to the one bucket, then write Gokapi's cloud configuration as its own user, readable by it only:

sudo install -o gokapi -g gokapi -m 0600 /dev/null /etc/gokapi/cloudconfig.yml
sudo nano /etc/gokapi/cloudconfig.yml
aws:
  Bucket: <your-bucket>
  Region: <bucket-region>
  KeyId: <access-key-id>
  KeySecret: <secret-access-key>
  Endpoint: ""            # leave empty for AWS S3, or https://<host> for an S3 compatible store
  ProxyDownload: false    # true streams downloads through Gokapi instead of redirecting to a pre-signed URL

Then restart Gokapi and check that it logged in to the bucket:

sudo systemctl restart gokapi
sudo journalctl -u gokapi -n 20 --no-pager | grep -iE 'aws|cloud storage'

Gokapi reports AWS login successful and Saving new files to cloud storage. Files already on the instance stay where they are; new uploads go to the bucket.

Step 13: Server components

Component Path
Gokapi binary (built from source with Go 1.27.3) /usr/local/bin/gokapi
Configuration (written at first boot) /etc/gokapi/config.json (gokapi, 0600)
Uploaded files, SQLite database and Gokapi's log /var/lib/gokapi/data
systemd unit gokapi.service (user gokapi, 127.0.0.1:53842)
nginx site /etc/nginx/sites-available/cloudimg-gokapi
Basic Auth password hash /etc/nginx/gokapi.htpasswd (root:www-data, 0640)
Certificate and key /etc/nginx/ssl/
First boot script /usr/local/sbin/gokapi-firstboot.sh
Host name helper /usr/local/sbin/gokapi-set-host
Administrator password helper /usr/local/sbin/gokapi-set-admin-password
Self test /usr/local/sbin/gokapi-selftest
Credentials /root/gokapi-credentials.txt (mode 0600)
Licence and build record /usr/share/doc/gokapi/LICENSE.md, /usr/share/doc/gokapi/BUILD-PROVENANCE.txt

Back up /etc/gokapi and /var/lib/gokapi/data together (stop Gokapi first, or snapshot the EBS volume): the database records each file, and the salts in config.json are needed for the stored passwords.

Never run /usr/local/bin/gokapi by hand without its configuration: with no config.json Gokapi starts its unauthenticated setup wizard on every network interface. Manage it with systemctl, which refuses to start it without the configuration.

Step 14: Security recommendations

  • Allow port 22 in the security group from your own networks only; open 80 and 443 only to the people who should use the service.
  • Keep both passwords private and change them if they may have leaked (Step 11).
  • Use your own DNS name and a certificate your users trust (Step 10), so nobody learns to click through certificate warnings.
  • Give share links a download limit and an expiry, and a password for anything sensitive.
  • Keep the operating system patched; unattended security upgrades are on, and sudo apt-get update && sudo apt-get upgrade applies everything else.

Support and licensing

Gokapi is free software under the GNU Affero General Public License, version 3; a copy is at /usr/share/doc/gokapi/LICENSE.md. This image runs the unmodified Gokapi 2.2.4 source from https://github.com/Forceu/Gokapi, built with the newer dependency versions listed in /usr/share/doc/gokapi/BUILD-PROVENANCE.txt. There is no per user or per CPU 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