Espial
June 8, 2026 ยท View on GitHub
This repository contains the instruction and commands for running Espial from the pre-built docker images on Docker Hub.
Espial
Espial is an open-source, web-based bookmarking server.
It allows mutiple accounts, but currently intended for self-host scenarios.
The bookmarks are stored in a sqlite3 database, for ease of deployment & maintenence.
The easist way for logged-in users to add bookmarks, is with the "bookmarklet", found on the Settings page.
Source Repository
https://github.com/jonschoning/espial
Running the pre-built Docker Hub Image (POSIX Only)
- These commands use
docker composewith settings indocker-compose.yml - see
Makefilefor additional commands
- Clone this repository
git clone https://github.com/jonschoning/espial-docker
cd espial-docker
- Pull the image from Docker Hub
make pull
- Start Espial
./espial-svc-start
- When the app starts, it should create the DB
espial.sqlite3in the current directory (or according todocker-compose.yml)
- Create a user
docker compose exec espial ./migration createuser --userName myusername --userPassword myuserpassword
- see
docker compose exec espial ./migrationfor all available cli commands - use the
/app/data/file prefix to access files on the host according to the bind mount volume inside the container, seedocker-compose.yml
- Import a pinboard bookmark file for a user (optional)
docker compose exec espial ./migration importbookmarks --userName myusername --bookmarkFile /app/data/sample-bookmarks.json
- Import a firefox bookmark file for a user (optional)
docker compose exec espial ./migration importfirefoxbookmarks --userName myusername --bookmarkFile /app/data/firefox-bookmarks.json
- Stop Espial
./espial-svc-stop
SystemD Service
copy this repo to /opt/espial/
a serivce unit is provided at etc/systemd/system/espial.service
which references:
espial-svc-startespial-svc-stop
adjust espial-svc-start to control where logs are stored.
Base Image
jonschoning/espial:espial
is based on
gcr.io/distroless/base-debian12
Defaults
As specified in docker-compose.yml:
- internal app port
3000is exposed to port80on host - adjust as necessary
Request IP Logging
Espial supports the IP_FROM_HEADER environment variable for request logging.
IP_FROM_HEADER=true: log the client IP from theX-Real-IPorX-Forwarded-Forheader when present, and fall back to the peer address if neither header is available.IP_FROM_HEADER=false: log the peer address from the HTTP connection.
Only set IP_FROM_HEADER=true if your application is safely positioned behind a trusted reverse proxy.
SSL / Reverse Proxy
Espial does not terminate TLS itself. Run it behind a reverse proxy that handles HTTPS and forwards traffic to Espial over HTTP.
For container-based deployment examples, including production-oriented layouts, see the espial-docker repository:
Minimal Caddy example:
Localhost without a real domain:
https://localhost:3050 {
reverse_proxy localhost:3000
}
or with a domain:
espial.example.com {
reverse_proxy 127.0.0.1:3000
}
With the domain setup:
- Caddy terminates TLS for
espial.example.com. - Espial continues listening on HTTP, locally on
127.0.0.1:3000- If using Docker Compose, it would like like
espial:3000
- If using Docker Compose, it would like like
- Set
IP_FROM_HEADER=trueonly when Espial is reachable solely through that trusted proxy.
If you are using Cloudflare:
- Prefer Cloudflare SSL mode
Full (strict). - use
header_up X-Forwarded-For {http.request.header.CF-Connecting-IP} - If traffic can reach Espial directly without passing through your trusted proxy, do not enable
IP_FROM_HEADER=true, because client IP headers can be spoofed.