
Deploy SFTPGo | (Just Updated) SFTP Server, Files and Host Keys Survive Redeploys
SFTP server whose uploads, users and host keys survive every redeploy
sftpgo
Just deployed
/var/lib/sftpgo
Deploy and Host SFTPGo on Railway
SFTPGo is a fully featured SFTP, FTP and WebDAV server with a web admin panel, a web client, a REST API, per-user virtual filesystems, quotas, and pluggable storage backends. This template runs it as a single service on a Railway volume, with SFTP exposed on a public TCP proxy and the admin panel on an HTTPS domain.
About Hosting SFTPGo
SFTPGo on Railway needs three things that are easy to get wrong, and this template fixes all three.
Everything stateful lives on the one volume. Upstream stores user home directories at
/srv/sftpgo/data and regenerates SSH host keys into /etc/sftpgo on every boot, so a
template that mounts only /var/lib/sftpgo loses every uploaded file on redeploy and makes
every SFTP client warn about a changed host key. This image relocates the SQLite data
provider, all user home directories, the backup directory and the host keys onto the single
Railway volume at /var/lib/sftpgo. Verified: a file uploaded over SFTP and the SSH host
key fingerprint were both unchanged after a full redeploy.
The admin account is sealed at deploy time. The admin password is generated per deploy as a Railway secret, and the container refuses to start if it is empty, so the install is never left with a well-known password or an unclaimed setup page on a public URL.
API tokens are not bound to the client IP. Railway's edge address rotates between
requests, so SFTPGo's default IP-bound tokens are rejected on the second REST call and the
admin session drops. This image turns that binding off and reads the real client address
from X-Forwarded-For instead.
The image is ghcr.io/bon5co/sftpgo-railway, pinned by digest and built from upstream
drakkan/sftpgo 2.7.5, also pinned by digest. Source:
bon5co/sftpgo-railway.
Which protocols are actually reachable. SFTP is public over Railway's TCP proxy, at the
host and port in RAILWAY_TCP_PROXY_DOMAIN / RAILWAY_TCP_PROXY_PORT. The web admin
panel, the web client and the REST API are public over HTTPS on the service domain. FTP and
FTPS are not exposed: they need a passive port range, and Railway's TCP proxy gives one
port per service. WebDAV is disabled for the same reason — one service gets one HTTP domain,
and it is used by the admin panel.
Why Deploy SFTPGo on Railway
Railway gives you a persistent volume, an HTTPS domain and a raw TCP endpoint from one deploy, which is exactly the shape SFTPGo needs — a file server is useless without durable storage and a public wire-protocol port. There is no VM to patch and no reverse proxy to configure, and the whole thing runs in about 25 MB of RAM, so it fits comfortably inside a Trial or Hobby plan service.
Common Use Cases
- Give a client or a partner an SFTP drop box without handing out a server login.
- Receive nightly batch files from a vendor whose only integration is SFTP.
- Front an S3, Google Cloud Storage or Azure Blob bucket with SFTP, FTP or a web UI.
- Hand non-technical users a browser upload page backed by the same storage as SFTP.
Dependencies for SFTPGo Hosting
None. This is a single service with a SQLite data provider on its own volume — no external database, no cache, no object store required. S3, GCS, Azure Blob and SFTP-to-SFTP backends can be configured per user afterwards, from the admin panel.
Deployment Dependencies
Implementation Details
After the deploy, open the service domain and sign in to /web/admin as admin with the
generated SFTPGO_DEFAULT_ADMIN_PASSWORD from the service variables. Create your first
user there, then connect with any SFTP client:
sftp -P $RAILWAY_TCP_PROXY_PORT @$RAILWAY_TCP_PROXY_DOMAIN
User home directories are created under /var/lib/sftpgo/data, on the volume.
There is no HTTP healthcheck configured, and that is deliberate: when a service has a TCP
proxy, Railway's healthcheck probes the TCP application port, which here speaks SSH rather
than HTTP, so any healthcheck path would fail the deploy. The restart policy is
ON_FAILURE with 10 retries instead.
Template Content