Fast, secure, containerized enterprise file sharing
Self-hosted WeTransfer-style alternative with Active Directory integration
Italian version: README.it.md
GoPulley is an internal file-sharing application for enterprise and public organizations. Authenticated users (Active Directory / LDAP) can upload files and share them with temporary links and configurable expiration.
The app runs in a single lightweight container, with no external runtime stack.
| Feature | Details |
|---|---|
| AD/LDAP authentication | Direct bind to Domain Controller, supports ldap:// and ldaps:// |
| Optional group restriction | Limit access to members of one AD group (memberOf) |
| Modern upload UI | Drag and drop workflow with HTMX, no full page refresh |
| Configurable expiration | 1 / 7 / 30 days / 1 year plus max constraints |
| Public links | Recipients can download using the link |
| Optional link password | Add password protection at share creation |
| Optional max downloads | Auto-expire links after N downloads |
| Chunked/resumable upload | Large files are uploaded in chunks and can resume |
| User upload quotas | Per-user storage quota (USER_QUOTA_MB) |
| Admin dashboard | Global file inventory and disk usage visibility |
| Automatic cleanup | Removes expired shares and stale upload sessions |
| Optional SHA-256 | Compute and show checksum for integrity verification |
| Single container deploy | Docker/Podman, SQLite embedded |
GoPulley is intentionally simple:
cmd/server/main.go: HTTP server, routes, sessions, handlersinternal/auth/ldap.go: LDAP bind and group checksinternal/database/sqlite.go: schema + CRUDinternal/storage/file.go: file persistence and streamingweb/templates/*: server-side HTML templatesweb/static/*: CSS and vendored HTMX
Persistent data lives under /data in the container:
- SQLite database (
/data/gopulley.db) - uploaded files (
/data/uploads/...)
- Podman 4.7+ (or Docker with Compose plugin)
# 1) Download runtime files
curl -O https://raw.githubusercontent.com/mirkochipdotcom/GoPulley/main/compose.yml
curl -O https://raw.githubusercontent.com/mirkochipdotcom/GoPulley/main/.env.example
# 2) Configure env
cp .env.example .env
# Edit .env for LDAP; keep LDAP_HOST=mock for local dev
# 3) Create data dir and start
mkdir -p ./data/uploads
podman compose up -dOpen http://localhost:8080.
Docker works the same way (docker compose ...).
By default, host data is mapped to ./data.
Use DATA_DIR in .env to move DB/uploads to another disk or a mounted network path.
DATA_DIR=./data
# DATA_DIR=/mnt/storage/gopulley
# DATA_DIR=/mnt/nas/gopulleyCopy .env.example to .env and adjust values.
SESSION_SECRETSECURE_COOKIESLDAP_HOST,LDAP_BASE_DN,LDAP_USER_DN_TEMPLATELDAP_REQUIRED_GROUP,LDAP_ADMIN_GROUP,ADMIN_USERS,LDAP_TLS_SKIP_VERIFYMAX_GLOBAL_DAYS,MAX_UPLOAD_SIZE_MB,USER_QUOTA_MBUPLOAD_CHUNK_SIZE_MB,UPLOAD_SESSION_TTL_HOURS,MAX_UPLOAD_SESSIONS_PER_USERPUBLIC_BASE_URL,DATA_DIR,DB_PATH,UPLOAD_DIRENABLE_SHA256
- Chunk size defaults to 10 MB (
UPLOAD_CHUNK_SIZE_MB) - In-progress sessions are auto-expired (
UPLOAD_SESSION_TTL_HOURS) - Concurrent in-progress uploads per user are capped (
MAX_UPLOAD_SESSIONS_PER_USER)
- Optional password at upload time
- Optional max download count ("burn after N downloads")
- SMTP link sharing is configured via
SMTP_SERVER,SMTP_PORT,SMTP_SECURITY,SMTP_USER,SMTP_PASSWORD,SMTP_FROM SMTP_USER_AUTH=true: uses authenticated AD user email/password for sending (where supported)SMTP_USER_AUTH=false: uses shared SMTP sender credentials and messages should be treated as non-monitored mailbox (no-reply)
To protect credentials stored in session cookies (when SMTP_USER_AUTH=true), GoPulley implements:
- Dual-key encryption: cookies encrypted with AES-256 using a key derived from
SESSION_SECRET - Dynamic
Secureflag: automatic protocol detection viaX-Forwarded-Protoheader
GoPulley automatically detects if the original request was HTTPS by reading the X-Forwarded-Proto header set by the reverse proxy:
# Nginx example
proxy_set_header X-Forwarded-Proto $scheme;# Traefik example (automatic with entryPoints)
labels:
- "traefik.http.routers.gopulley.entrypoints=websecure"
- "traefik.http.routers.gopulley.tls=true"With this configuration:
- Browser → Reverse Proxy: HTTPS (TLS terminated at proxy)
- Reverse Proxy → GoPulley: HTTP local (trusted network)
- Cookie
Secureflag: automaticallytruebecauseX-Forwarded-Proto: https
If the X-Forwarded-Proto header is not present (direct access without reverse proxy), GoPulley uses the SECURE_COOKIES variable:
# Direct HTTPS access to the app (no reverse proxy)
SECURE_COOKIES=true
# Direct HTTP access (local testing only - NOT for production)
SECURE_COOKIES=falseNote: in production with a properly configured HTTPS reverse proxy, SECURE_COOKIES is ignored and the Secure flag is set automatically.
UPN style (modern AD):
LDAP_HOST=ldaps://dc.example.com:636
LDAP_BASE_DN=DC=example,DC=com
LDAP_USER_DN_TEMPLATE=%s@example.comClassic DN style:
LDAP_HOST=ldap://ldap.example.com:389
LDAP_BASE_DN=dc=example,dc=com
LDAP_USER_DN_TEMPLATE=uid=%s,ou=Users,dc=example,dc=com# first run
podman compose up -d
# update to latest image
podman compose pull && podman compose up -d
# logs
podman compose logs -f
# stop
podman compose downImages are published automatically on GitHub Container Registry on tag push.
# latest
podman pull ghcr.io/mirkochipdotcom/gopulley:latest
# specific tag
podman pull ghcr.io/mirkochipdotcom/gopulley:0.9.8Requires Go 1.22+ and gcc (go-sqlite3 uses CGO).
CGO_ENABLED=1 go build -ldflags="-s -w" -o gopulley ./cmd/serverRun local dev:
LDAP_HOST=mock SESSION_SECRET=dev-secret ./gopulleyUI strings are served via i18n bundles. Current supported locales in code:
enitesdefr
Locale is resolved from Accept-Language with fallback to English.
GNU AGPLv3 - see LICENSE.