Deployment guide

Plik 1.4.2

Overview

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

Plik is a self-hosted temporary file sharing service. You upload one or more files in its web interface, with its API or with a small command-line client, and get a short link to share. Every upload has an expiry (up to 30 days by default), after which Plik deletes it. Your files stay on your own instance.

Uploads can also be one-shot (deleted after the first download) or streamed (sent straight from the uploader to the downloader without being stored). They can be protected by a password, and they can carry a Markdown comment.

What you get:

  • Uploads need an account. Upstream Plik accepts uploads from anyone by default. This image forces authentication: only signed-in users and API tokens can upload, and there is no self-registration, because the administrator creates accounts. Download links still work for anyone who has them.
  • An administrator unique to your instance. First boot creates the database, the admin account (Plik generates its password) and an API token. It writes them to /root/plik-credentials.txt, which is readable by root only. Nothing is baked into the image, and the web sessions are signed with a key generated on your instance.
  • HTTPS from the first boot. nginx serves Plik on port 443 with a certificate generated on your instance, and 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.
  • Built from source with current dependencies. The upstream 1.4.2 server binary was built with Go 1.26.1 and carries 75 known vulnerabilities in the Go standard library and its modules. This image compiles Plik 1.4.2 from its source with Go 1.27.3 and the fixed releases of golang.org/x/net, golang.org/x/crypto, gRPC, pgx and others. It also rebuilds the web interface with fixed releases of Mermaid and DOMPurify, which render the Markdown comments on download pages. The web interface loads no fonts or scripts from other sites. The build record is in /usr/share/doc/plik/BUILD-PROVENANCE.txt.
  • Hardened defaults. Plik listens on 127.0.0.1 only and runs as its own unprivileged user under a locked-down systemd unit. Plik and nginx are blocked from the instance metadata service, and the AMI requires IMDSv2. The client address Plik records comes from the connection, never from a header a client can forge. Uploaded HTML, SVG and script files are always downloaded and never rendered in the browser.
  • Files on their own volume. Uploads and Plik's database live on a separate 30 GiB EBS volume mounted at /var/lib/plik. You can make it bigger at launch or later.
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.

What is on the image: Plik 1.4.2 (/opt/plik/plikd and its web interface), the Plik bash client for download, nginx, SQLite, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. Plik's database is a local SQLite file, so there is no database port.

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, uploads 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
1

Launch the instance

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

The AMI has two volumes: the 8 GiB root volume (/dev/sda1) and the 30 GiB data volume (/dev/sdf) that holds every upload. Set the data volume to the space you expect to share. Plik accepts files of up to 10 GB each by default.

To launch with the AWS CLI instead, replace the values in angle brackets. This command makes the data volume 100 GiB:

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/sdf,Ebs={VolumeSize=100,VolumeType=gp3}' \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=plik}]'

If you make the data volume bigger than 30 GiB, grow its file system once after the first boot (Step 11).

2

Connect to your instance

Connect over SSH as the ubuntu user. This is the SSH user for the Plik 1.4.2 on Ubuntu 24.04 version.

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

Check the services

First boot takes a few seconds. Afterwards, Plik, nginx and the first-boot unit are all active:

systemctl is-active plik nginx plik-firstboot
active active active

nginx is the only web listener. Plik itself listens on 127.0.0.1 only:

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

The number of nginx entries follows the number of vCPUs. The server reports its release and the Go toolchain it was built with:

/opt/plik/plikd --version
plikd version 1.4.2 built from git rev ed7f43fb [release] at <build time> UTC with go1.27.3 linux/amd64
4

Get your URL, password and API token

Print the credentials file:

sudo cat /root/plik-credentials.txt

The file holds the address Plik is served at (your instance's public IP address by default), the administrator password and the API token, all generated on this instance:

# Plik 1.4.2 - generated on first boot by plik-firstboot.service. Unique to this instance; keep it safe. plik.url=https://<public-ip>/
# Web UI login (Sign in, then Admin to add users): plik.admin.user=admin plik.admin.pass=<32 letters and digits>
# API token for scripts and the bash client (HTTP header "X-PlikToken: <token>"): plik.api.token=<token>
# Uploads need a login or a token (anonymous uploads are disabled). Download links work for anyone who has them.
# Change the host name:
sudo plik-set-host <dns-name>
# Change the admin password: in the web UI (Admin > Users > admin > Edit), then update this file.

Plik's settings are in /etc/plik/plikd.cfg. First boot set the address used in share links (PlikDomain), forced authentication, and set Plik to listen on 127.0.0.1:

sudo grep -E '^(ListenAddress|ListenPort|PlikDomain|SourceIpHeader|FeatureAuthentication|FeatureLocalLogin|FeatureApiTokens|MaxFileSizeStr|DefaultTTLStr|MaxTTLStr)' /etc/plik/plikd.cfg
ListenAddress = "127.0.0.1" ListenPort = 8080 PlikDomain = "https://<public-ip>" SourceIpHeader = "X-Real-IP" MaxFileSizeStr = "10GB" DefaultTTLStr = "30d" MaxTTLStr = "30d" FeatureAuthentication = "forced" FeatureLocalLogin = "enabled" FeatureApiTokens = "enabled"
5

Sign in

Open plik.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).

Choose Login and sign in as admin with plik.admin.pass:

6

Upload and share files

The Upload page takes files by drag and drop, paste or a file picker. Before you upload, choose the options you want: destruct after download (one-shot), streaming, removable by the downloader, end-to-end encryption, a password, a Markdown comment, and how long the upload is kept:

After the upload, Plik shows the upload's page. It lists the share link, the admin link (which lets you add or delete files later), the comment and each file with its own link:

Anyone with the share link sees the files and can download them without an account. The upload disappears when it expires, or after the first download for a one-shot upload:

7

Your uploads, tokens and users

Your name at the top right opens your account page. Uploads lists everything you have shared, with remove buttons. Tokens lists your API tokens and creates new ones. Edit account changes your password:

Admin shows the server's statistics, every upload and the users. There is no self-registration, so add an account for each person who should upload by choosing Create User.

To change the administrator password, choose Edit on the admin row. Then update plik.admin.pass in /root/plik-credentials.txt:

8

Upload from scripts

Every upload needs a token or a session. Send the token in the X-PlikToken header, and keep it out of the command line by reading the header from a file. On the instance, run:

sudo sed -n 's/^plik.api.token=/X-PlikToken: /p' /root/plik-credentials.txt > ~/.plik-token && chmod 600 ~/.plik-token
H=$(sudo sed -nE 's#^plik.url=https://([^/]+)/.*#\1#p' /root/plik-credentials.txt)
echo "hello from Plik" > hello.txt
UP=$(curl -sk --resolve "$H:443:127.0.0.1" -H @"$HOME/.plik-token" -H 'Content-Type: application/json' -d '{"ttl":86400}' "https://$H/upload")
ID=$(echo "$UP" | jq -r .id)
curl -sk --resolve "$H:443:127.0.0.1" -H @"$HOME/.plik-token" -F "file=@hello.txt" "https://$H/file/$ID" | jq -r '"https://'"$H"'/file/'"$ID"'/" + .id + "/" + .fileName'

The last command prints the direct download link of the file, for example https://<public-ip>/file/<upload-id>/<file-id>/hello.txt. The upload's page is https://<public-ip>/#/?id=<upload-id>.

From your own computer, use the same calls without --resolve, and with -k until you install a trusted certificate (Step 10).

The image also serves Plik's bash client, which uses curl, at https://<public-ip>/clients/bash/plik.sh. Run it on your own computer (Linux or macOS), with the server address in PLIK_URL and the token in ~/.plikrc:

curl -k -o plik.sh https://<public-ip>/clients/bash/plik.sh printf 'Token = "%s"\n' '<plik.api.token>' > ~/.plikrc && chmod 600 ~/.plikrc PLIK_URL=https://<public-ip> bash plik.sh -k -t 1d report.pdf
Create new upload on https://<public-ip>... --> https://<public-ip>/#/?id=<upload-id> Uploading files... curl -s 'https://<public-ip>/file/<upload-id>/<file-id>/report.pdf' > 'report.pdf'

The client prints the upload's link and a download command for each file. These options are useful:

  • -k accepts the self-signed certificate. Drop it once you install a trusted certificate (Step 10).
  • -o makes the upload one-shot.
  • -c "<text>" adds a comment.
  • bash plik.sh -h lists every option.

The Go command-line client (plik) is not included in this image. Download it from the Plik releases if you want it, and point it at your server with the same token.

9

Check the security model

The image ships a self-test that proves the credential model over HTTPS. It checks four things. An anonymous upload is refused. The API token uploads a file that an anonymous downloader gets back byte for byte, and the test upload is then removed. The administrator password signs in. A wrong password is refused.

Run the self-test:

sudo /usr/local/sbin/plik-selftest
OK: anonymous upload refused; token upload + anonymous download round-trip over TLS; admin login works, wrong password 403

Plain HTTP redirects to HTTPS. Uploads and the user list refuse you without credentials, and a request for a host name the instance does not serve gets no answer:

H=$(sudo sed -nE 's#^plik.url=https://([^/]+)/.*#\1#p' /root/plik-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 -w '\nanonymous upload: %{http_code}\n' --resolve "$H:443:127.0.0.1" -X POST -H 'Content-Type: application/json' -d '{}' "https://$H/upload"
curl -sk -o /dev/null -w 'user list without a session: %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/users"
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>/ unable to create upload : anonymous uploads are disabled anonymous upload: 400 user list without a session: 401 unknown host name: 000

Plik and nginx cannot reach the instance metadata service. nginx passes Plik the address of the connection and overwrites any forwarded address a client sends. The secrets are readable by root (or Plik's own user) only:

systemctl show plik nginx -p Id -p IPAddressDeny grep -E 'proxy_set_header (Host|X-Real-IP|X-Forwarded-For)' /etc/nginx/plik-proxy.conf
sudo stat -c '%a %U:%G %n' /root/plik-credentials.txt /etc/plik/plikd.cfg /var/lib/plik/plik.db /etc/nginx/ssl/plik.key
IPAddressDeny=169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 Id=plik.service IPAddressDeny=169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 Id=nginx.service proxy_set_header Host $plik_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; 600 root:root /root/plik-credentials.txt 640 root:plik /etc/plik/plikd.cfg 640 plik:plik /var/lib/plik/plik.db 600 root:root /etc/nginx/ssl/plik.key

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

H=$(sudo sed -nE 's#^plik.url=https://([^/]+)/.*#\1#p' /root/plik-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 = sac 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
10

Your own DNS name and certificate

Point a DNS record at the instance, then set the name that Plik is served as. The command below does the following:

  • Creates a new self-signed certificate for the name.
  • Updates nginx, Plik's PlikDomain (the address in share links) and the URL in /root/plik-credentials.txt.
  • Restarts Plik.
  • Keeps the name across reboots.

Run it:

sudo plik-set-host <your-domain>

To use a certificate from your own certificate authority instead, copy it over the generated pair and reload nginx. Running plik-set-host again replaces it with a self-signed certificate:

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

Storage

Uploads (/var/lib/plik/files) and Plik's SQLite database (/var/lib/plik/plik.db) are on the data volume:

df -h /var/lib/plik
Filesystem Size Used Avail Use% Mounted on /dev/nvme1n1 30G 3.4M 28G 1% /var/lib/plik

To make the volume bigger, increase its size in the EC2 console (Volumes, Modify volume) or with aws ec2 modify-volume. Then grow the file system online. The device name can differ between instance types, so take it from findmnt:

sudo resize2fs "$(findmnt -no SOURCE /var/lib/plik)"

Plik can also keep files in S3 or an S3-compatible store. Set DataBackend = "s3" with an Endpoint, Bucket, AccessKeyID and SecretAccessKey in [DataBackendConfig] of /etc/plik/plikd.cfg, and see the Plik documentation.

It needs an access key for the bucket. An EC2 instance role is not used, because Plik's S3 client takes static keys only and this image blocks Plik from the instance metadata service. Create an IAM user limited to the one bucket, then restart Plik with sudo systemctl restart plik.

12

Server components

Each item lists a component and its path:

  • Plik server (built from source with Go 1.27.3): /opt/plik/plikd
  • Web interface, bash client and release notes: /opt/plik/webapp/dist, /opt/plik/clients/bash/plik.sh and /opt/plik/changelog
  • Configuration: /etc/plik/plikd.cfg (root:plik, 0640)
  • Uploaded files and SQLite database (data volume): /var/lib/plik
  • systemd unit: plik.service (user plik, 127.0.0.1:8080)
  • nginx site: /etc/nginx/sites-available/sac-plik
  • Certificate and key: /etc/nginx/ssl/
  • First-boot script: /usr/local/sbin/plik-firstboot.sh
  • Host name helper: /usr/local/sbin/plik-set-host
  • Self-test: /usr/local/sbin/plik-selftest
  • Credentials: /root/plik-credentials.txt (mode 0600)
  • License and build record: /usr/share/doc/plik/LICENSE and /usr/share/doc/plik/BUILD-PROVENANCE.txt

Back up /var/lib/plik (stop Plik first, or snapshot the data volume) and /etc/plik/plikd.cfg. Plik deletes expired uploads by itself.

Plik's own command-line administration works through the same configuration file, as the plik user. For example, to list the users, run:

sudo -u plik /opt/plik/plikd --config /etc/plik/plikd.cfg user list
13

Security recommendations

  • Allow port 22 in the security group from your own networks only. Open ports 80 and 443 only to the people who should use the service.
  • Keep the administrator password and the API token private. If they may have leaked, change the password (Step 7), and revoke and recreate the token on the Tokens page.
  • Use your own DNS name and a certificate your users trust (Step 10), so nobody learns to click through certificate warnings.
  • Keep the expiry short, and use one-shot uploads or 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

Plik is free software under the MIT license. A copy is at /usr/share/doc/plik/LICENSE.

This image runs the unmodified Plik 1.4.2 source from https://github.com/root-gg/plik, built with the newer dependency versions listed in /usr/share/doc/plik/BUILD-PROVENANCE.txt and without the web interface's links to Google Fonts. 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 Plik 1.4.2 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