Vaultwarden with Docker Compose (Short Answer)
Vaultwarden is a lightweight, self-hosted reimplementation of the Bitwarden server, written in Rust. Default port: the container listens on port 80 internally; map it to any host port you like, or publish nothing and let your reverse proxy reach it over a Docker network. There is no second port any more: the old WebSocket port 3012 was removed in v1.31.0. It speaks the same API as Bitwarden, so every official Bitwarden app and browser extension works against it unchanged, and it runs comfortably in under 100 MB of RAM on a Raspberry Pi. You deploy it with a Docker Compose file, put a reverse proxy in front of it for HTTPS, keep public signups off, and invite your users from the admin panel.
In December 2022, LastPass disclosed that attackers had stolen encrypted password vaults for millions of users. Not metadata. Not email addresses. The actual vaults. The ones containing every password, every note, every saved card. LastPass assured everyone that vaults were safe as long as users had strong master passwords. Within months, security researchers linked over $35 million in cryptocurrency theft to cracked LastPass vaults.
From the homelab: I moved my entire password management to a self-hosted Vaultwarden instance. Same Bitwarden apps on every device, but the vault lives on my infrastructure, not someone else’s cloud. For something as critical as passwords, that matters.
I moved my entire family off LastPass to Vaultwarden shortly after that breach. Not because I thought my vault had been compromised, but because the breach revealed something I already suspected: trusting a third party with the keys to your entire digital life is a choice, not a requirement. And it is a choice you should question.
Vaultwarden is that alternative. A lightweight, self-hosted password manager that is fully compatible with all Bitwarden apps and browser extensions, runs on minimal hardware, and puts you in complete control of where your passwords live. This guide walks you through setting it up properly, from first container to family deployment, with the backup strategy that makes self-hosting passwords responsible rather than reckless.
Career Context: Identity and access management is a core competency in every infrastructure role. Understanding password vaults, secrets management, and credential lifecycle translates directly to enterprise tools like HashiCorp Vault, Azure Key Vault, and CyberArk. Self-hosting a password manager teaches you about TLS, database backups, and security hardening in a context where the stakes feel real, because they are.
What Is Vaultwarden?
Vaultwarden (formerly bitwarden_rs) is an unofficial, community-built server implementation of the Bitwarden API, written in Rust. It is not a fork of Bitwarden. It is a clean-room reimplementation that speaks the same protocol, which means every official Bitwarden client works with it: the browser extensions, the desktop apps, the mobile apps, and the CLI tool.
Why not just use the official Bitwarden server? The standard official self-hosted deployment runs as a set of containers on Microsoft SQL Server and needs significantly more resources. Bitwarden’s single-container “lite” deployment (out of beta since December 2025, with SQLite, PostgreSQL and MySQL/MariaDB support) narrows that gap, but it still asks for more memory than Vaultwarden, which runs as a single container, uses SQLite by default, and comfortably operates on a Raspberry Pi. For a homelab or small family deployment, it is exactly what you need and nothing you do not.
Key features:
- Full Bitwarden client compatibility – every official app works unmodified
- Organisations and collections – share passwords with family members
- Attachments and Send – secure file sharing
- TOTP generation – built-in two-factor code support
- Admin panel – web-based user and configuration management
- Lightweight – a small family instance typically uses well under 100 MB of RAM
Prerequisites
Before you start, you will need:
- Docker and Docker Compose installed on your server. If you have not done this yet, follow the Docker installation guide for Ubuntu 24.04.
- A domain name (or a free DuckDNS subdomain). Vaultwarden requires HTTPS to function properly, and the Bitwarden clients will refuse to connect over plain HTTP. If you do not own a domain yet, set up DuckDNS for a free subdomain that will work perfectly for this.
- A reverse proxy with TLS. Nginx Proxy Manager is the easiest option for most home labs, and it handles Let’s Encrypt certificates automatically. If you already have Caddy, Traefik, or plain Nginx with certbot, those work fine too.
- A machine that stays on. This is your password manager. If it is offline, nobody in your household can log in to anything new. A Pi, a mini PC, or a VM on your homelab server all work. Set up Uptime Kuma monitoring to alert you the moment it goes down.
Understand the responsibility. Self-hosting your passwords means you are responsible for uptime, backups, and security. If your server dies and you have no backup, your passwords are gone. This guide covers backups thoroughly because they are non-negotiable. If the idea of that responsibility makes you uncomfortable, there is no shame in using Bitwarden’s hosted service. It is a good product run by good people.
Step 1: Create the Docker Compose File
Create a directory for your Vaultwarden deployment and set up the compose file:
mkdir -p ~/vaultwarden && cd ~/vaultwarden
Create a docker-compose.yml file:
services:
vaultwarden:
image: vaultwarden/server:latest # or pin a release, e.g. vaultwarden/server:1.37.3
container_name: vaultwarden
restart: unless-stopped
environment:
- DOMAIN=https://vault.yourdomain.com
- SIGNUPS_ALLOWED=false # invite users from the admin panel instead
- ADMIN_TOKEN=${ADMIN_TOKEN}
- SMTP_HOST=${SMTP_HOST}
- SMTP_FROM=${SMTP_FROM}
- SMTP_PORT=587
- SMTP_SECURITY=starttls
- SMTP_USERNAME=${SMTP_USERNAME}
- SMTP_PASSWORD=${SMTP_PASSWORD}
- LOG_LEVEL=warn
volumes:
- ./vw-data:/data
networks:
- proxy
# No published port: the reverse proxy reaches the container as vaultwarden:80
# over the shared proxy network. Only if your proxy runs directly on the host
# (not in Docker), publish to localhost instead of every interface:
# ports:
# - "127.0.0.1:8080:80"
networks:
proxy:
external: true
The compose file joins an external network called proxy. Create it once with docker network create proxy and attach your reverse proxy container to the same network.
Now generate the admin token in your shell with openssl rand -base64 48, then create a .env file alongside the compose file and paste the output in. A .env file does not run commands, so writing $(openssl ...) inside it would not work:
# Paste the output of: openssl rand -base64 48
ADMIN_TOKEN=paste-the-generated-token-here
# SMTP settings (for email verification and 2FA recovery)
SMTP_HOST=smtp.example.com
[email protected]
SMTP_USERNAME=your-smtp-user
SMTP_PASSWORD=your-smtp-password
Pro tip: Generate the admin token with openssl rand -base64 48 and save it somewhere safe before you need it. You will use this to access the admin panel. Losing it means you cannot administer Vaultwarden without editing the container’s environment directly. From Vaultwarden 1.28+, you can also use an Argon2 hashed admin token for better security. Run docker exec -it vaultwarden /vaultwarden hash to generate one, and wrap the result in single quotes in .env (ADMIN_TOKEN='$argon2id$...') so Compose does not treat its $ signs as variables.
Step 2: Start the Container
docker compose up -d
Verify it is running:
docker compose logs -f vaultwarden
You should see Vaultwarden starting up on port 80 inside the container. Because no port is published on the host, nothing outside Docker can reach it yet. That is deliberate: the only way in will be through the HTTPS reverse proxy you set up next.
Step 3: Set Up HTTPS
This is not optional. The Bitwarden clients require HTTPS, and you are transmitting passwords. Running a password manager over plain HTTP would be negligent.
If you are using Nginx Proxy Manager (which I recommend for homelabs), the process is straightforward:
- Point your domain (e.g.,
vault.yourdomain.com) to your server’s IP via a DNS A record - In Nginx Proxy Manager (attached to the same
proxynetwork), create a new proxy host with forward hostnamevaultwardenand port80 - Enable the SSL tab and request a Let’s Encrypt certificate
- Turn on “Force SSL” and “HTTP/2 Support”
- Under the “Websockets Support” toggle, turn it on. Modern Vaultwarden serves WebSocket notifications over the same HTTP port, so no separate location block is needed
If your proxy does not have a WebSockets toggle, pass the upgrade headers on the main location instead. Everything, including live sync, goes to the one port. For plain Nginx running on the host, with the localhost-only port mapping from the comment in the compose file:
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
Once HTTPS is working, navigate to https://vault.yourdomain.com. You should see the Bitwarden web vault login page.
Putting a reverse proxy in front of Vaultwarden
Vaultwarden must be served over HTTPS. The Bitwarden clients refuse to talk to a plain HTTP endpoint that is not localhost, and the browser extension needs a secure context for the Web Crypto API. The container does not terminate TLS itself, so a reverse proxy is not optional decoration here, it is part of the install.
One thing that trips people up on older guides: Vaultwarden used to need a second port, 3012, published for WebSocket notifications so that vault changes synced live between devices. That is gone. WebSocket notifications have been served over the main HTTP port since v1.29.0, and WEBSOCKET_ENABLED and WEBSOCKET_PORT have been ignored since then; v1.31.0 removed port 3012 support entirely. If you are copying a compose file that publishes 3012, delete that line. Set ENABLE_WEBSOCKET=false if you actually want it off.
Nginx Proxy Manager
The easiest option if you want a web interface rather than config files, and the one most home labs already have running. Add a Proxy Host with your domain, scheme http, forward hostname vaultwarden (the container name) and port 80. Turn on “Websockets Support” on the Details tab and “Block Common Exploits”. Then take the certificate from the SSL tab with “Force SSL” and “HTTP/2 Support” enabled.
Put Nginx Proxy Manager and Vaultwarden on the same Docker network and forward to the container name, not to the host IP. That keeps the traffic off your LAN and means you do not have to publish Vaultwarden’s port on the host at all.
Walkthrough: Nginx Proxy Manager with Docker.
Caddy
The shortest configuration of the three, because Caddy obtains and renews certificates on its own with no extra step:
vault.example.com {
reverse_proxy vaultwarden:80
}
That is the whole Caddyfile entry. Caddy handles ACME, renewal and the WebSocket upgrade without being told. If you are standing up a reverse proxy purely for Vaultwarden and have no other requirements, this is the least that can go wrong.
Traefik
Worth it if you are already running Traefik, because the configuration lives on the container as labels and there is nothing separate to maintain:
labels:
- "traefik.enable=true"
- "traefik.http.routers.vaultwarden.rule=Host(`vault.example.com`)"
- "traefik.http.routers.vaultwarden.entrypoints=websecure"
- "traefik.http.routers.vaultwarden.tls.certresolver=letsencrypt"
- "traefik.http.services.vaultwarden.loadbalancer.server.port=80"
Note the port on the last line is the container’s internal port 80, not whatever you mapped on the host. Traefik reaches the container over the Docker network, so it does not need a published port either.
What to check once the proxy is up
- The site loads over HTTPS with a valid certificate, not a self-signed one. The mobile apps will not accept a certificate they cannot chain.
- Log in on a second device and change an item. The first device should update within a second or two. If it does not, WebSocket upgrades are not passing through the proxy.
/adminis reachable only if you meant it to be. See the hardening section below.- The container port is not also published straight to your LAN, bypassing the proxy entirely.
Step 4: Create Your Account and Configure the Admin Panel
Public signups are off in the compose file, so you create accounts by invitation. Open the admin panel at https://vault.yourdomain.com/admin, sign in with the admin token from your .env file, and invite your own email address under Users. With SMTP configured you get an invitation email; without it, go to https://vault.yourdomain.com/#/signup and register with the invited address. Use a strong, unique master password. This is the one password you need to remember, so make it long and memorable rather than complex and forgettable. A passphrase of four or five random words works well.
From the admin panel you can also:
- View and manage registered users
- Invite new users via email
- Configure SMTP settings
- Enable or disable features (attachments, Send, organisations)
- View server diagnostics
Pro tip: Leave SIGNUPS_ALLOWED=false as it is and invite each family member from the admin panel, which works regardless of the signup setting. Opening signups on a public-facing instance, even briefly, is asking for trouble.
Step 5: Import Your Existing Passwords
Moving from another password manager is straightforward. Vaultwarden supports imports from LastPass, 1Password, Chrome, Firefox, KeePass, Dashlane, and dozens of others.
- Export from your current manager (most offer a CSV or JSON export)
- In the Vaultwarden web vault, go to Tools > Import Data
- Select your source format from the dropdown
- Upload the file
- Delete the exported file immediately after import. It contains all your passwords in plain text.
Critical: Exported password files are unencrypted plain text. Do not leave them on your desktop, in your Downloads folder, or anywhere they might be synced to a cloud service. Import, verify the import worked, then securely delete the file. On Linux: shred -u export.csv. Do not just move it to the recycle bin.
After importing, spend some time organising. Create folders for logical groupings: Finance, Social Media, Work, Infrastructure, Family Shared. It takes an hour now and saves you time every day afterwards.
Step 6: Set Up Family Sharing with Organisations
One of the best features Vaultwarden inherits from Bitwarden is organisations. These let you share passwords with family members without everyone needing to know the same master password.
Here is how I have mine set up:
- Create an organisation (e.g., “Lonsdale Family”) from the web vault
- Create collections within it: “Streaming Services,” “Home Network,” “Shared Accounts”
- Invite family members via their email addresses (SMTP must be configured)
- Assign permissions per collection. The kids can see the Wi-Fi password but not the router admin credentials.
Each family member creates their own account with their own master password. They see shared credentials alongside their personal vault, but their personal items remain private. It is clean separation with selective sharing, exactly how enterprise credential management works.
Step 7: Backups (Non-Negotiable)
I cannot stress this enough. If you self-host your passwords without a backup strategy, you are one dead SSD away from being locked out of every account you own. This is the part that separates responsible self-hosting from recklessness.
Vaultwarden stores everything in the vw-data directory:
db.sqlite3– the database containing all vaultsattachments/– any files attached to vault entriessends/– Bitwarden Send filesconfig.json– runtime configurationrsa_key*– RSA keys used for authentication tokens
Here is the backup script I run nightly via cron:
#!/bin/bash
# vaultwarden-backup.sh
# Run nightly via cron: 0 2 * * * /home/teky/vaultwarden/backup.sh
set -euo pipefail
BACKUP_DIR="/home/teky/backups/vaultwarden"
VW_DATA="/home/teky/vaultwarden/vw-data"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30
mkdir -p "${BACKUP_DIR}"
# Use sqlite3 .backup for a consistent snapshot
# This is safe even while Vaultwarden is running
sqlite3 "${VW_DATA}/db.sqlite3" ".backup '${BACKUP_DIR}/db_${TIMESTAMP}.sqlite3'"
# Archive the full data directory (attachments, keys, config)
tar czf "${BACKUP_DIR}/vw-data_${TIMESTAMP}.tar.gz" \
-C "$(dirname ${VW_DATA})" \
"$(basename ${VW_DATA})"
# Remove backups older than retention period
find "${BACKUP_DIR}" -name "*.sqlite3" -mtime +${RETENTION_DAYS} -delete
find "${BACKUP_DIR}" -name "*.tar.gz" -mtime +${RETENTION_DAYS} -delete
echo "[$(date)] Backup completed: db_${TIMESTAMP}.sqlite3"
# Make it executable and add to cron
chmod +x /home/teky/vaultwarden/backup.sh
crontab -e
# Add: 0 2 * * * /home/teky/vaultwarden/backup.sh >> /var/log/vaultwarden-backup.log 2>&1
Critical: Store backups on a different physical device. Backing up to the same disk as Vaultwarden protects you against database corruption but not disk failure. I rsync mine to a separate machine nightly and keep an encrypted copy offsite. If this feels like overkill, remember what is in this database: every password you own.
Pro tip: Test your backups. At least once, copy a backup to a test machine, spin up a fresh Vaultwarden container pointing at it, and verify you can log in and see your data. An untested backup is not a backup, it is a hope.
Step 8: Hardening Your Instance
Once everything is working, lock it down:
Disable Public Signups
The compose file above already ships with signups off. If you ever turned them on, set this back in docker-compose.yml and recreate the container:
- SIGNUPS_ALLOWED=false
Secure the Admin Panel
If you do not need persistent admin access, disable it entirely after initial setup:
# Remove or comment out the ADMIN_TOKEN line to disable the admin panel
# - ADMIN_TOKEN=${ADMIN_TOKEN}
You can always re-enable it temporarily when needed by adding the token back and recreating the container. One catch: if you ever pressed Save in the admin panel, Vaultwarden wrote a config.json in the data directory, and its values take precedence over environment variables. The panel is only disabled when no ADMIN_TOKEN is set and there is no admin_token key in config.json.
Rate Limiting
Vaultwarden includes built-in login attempt limiting. You can tune it with:
- LOGIN_RATELIMIT_MAX_BURST=5
- LOGIN_RATELIMIT_SECONDS=60
Fail2Ban Integration
For additional brute-force protection, configure fail2ban to watch Vaultwarden’s logs. Add a filter at /etc/fail2ban/filter.d/vaultwarden.conf:
[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: \. Username:.*$
ignoreregex =
And a jail in /etc/fail2ban/jail.d/vaultwarden.local:
[vaultwarden]
enabled = true
port = http,https
filter = vaultwarden
# Traffic to a proxy published by Docker passes through the FORWARD chain,
# not INPUT, so bans in the default chain would not block it.
# Drop this line if your reverse proxy runs directly on the host.
chain = FORWARD
logpath = /home/teky/vaultwarden/vw-data/vaultwarden.log
maxretry = 5
bantime = 14400
findtime = 14400
Pro tip: For fail2ban to work, you need Vaultwarden to log to a file. Add LOG_FILE=/data/vaultwarden.log to your environment variables and ensure the real client IPs are being passed through your reverse proxy (check the X-Forwarded-For headers).
Step 9: Mobile and Browser Extensions
This is where self-hosting Vaultwarden really shines. You use the official Bitwarden apps, unchanged. No sideloading, no custom builds.
- Install the Bitwarden app from your phone’s app store (iOS or Android)
- On the login screen, open the “Logging in on” dropdown and choose “Self-hosted”
- Enter your server URL in the “Server URL” field:
https://vault.yourdomain.com - Log in with your account credentials
For the browser extension (available for Firefox, Chrome, Edge, Brave, and Safari):
- Install the Bitwarden extension from your browser’s extension store
- On the login screen, open the “Logging in on” dropdown and choose “Self-hosted”
- Enter your server URL in the “Server URL” field
- Log in
Auto-fill works identically to Bitwarden Cloud. Your phone can use Bitwarden as its system-wide autofill provider. The browser extension fills login forms automatically. The experience is indistinguishable from the hosted service, except the data never touches anyone else’s servers.
Troubleshooting Common Issues
Mobile App Cannot Connect
Almost always a TLS issue. The Bitwarden apps require a valid, trusted certificate. Self-signed certificates will not work on mobile. Use Let’s Encrypt via your reverse proxy. If you are on an internal-only network without a public domain, look into DNS challenge validation with Let’s Encrypt or use a split-horizon DNS setup with a real certificate.
Live Sync Not Working
If changes made on one device take time to appear on another, WebSocket notifications are not getting through. On current versions these travel over the same HTTP port as everything else, so the thing to check is that your reverse proxy passes the Upgrade and Connection headers. Check the configuration example in Step 3 above. If you are following an older guide that proxies port 3012 separately, that port no longer exists.
Import Fails or Duplicates Items
Some exporters produce malformed CSV files, particularly with entries containing commas or newlines in notes fields. Try the JSON export format if CSV fails. If you get duplicates, it is usually because you ran the import twice. You can purge the vault from Settings > Danger Zone and reimport cleanly.
Admin Panel Returns 404
Ensure ADMIN_TOKEN is set in your environment. If it is empty or not set, Vaultwarden disables the admin panel entirely. Recreate the container after adding or changing the token.
High Resource Usage
Vaultwarden is typically very light. If you see unexpected CPU or memory usage, check the log level. Setting LOG_LEVEL=warn or LOG_LEVEL=error reduces logging overhead. Also ensure you are not running icon caching on a large vault without sufficient disk space.
You Are Self-Hosting Your Passwords. Here Is What Else to Take Back.
Getting your passwords off someone else’s servers is a significant step toward digital sovereignty. But it is just one piece. If this is the first service you have self-hosted, it will not be the last. Once you experience what it feels like to own your infrastructure rather than rent it, you start looking at everything differently.
Here is where to go next:
- Build Your First Homelab – if you set up Vaultwarden on a spare machine, this guide helps you turn that machine into a proper platform for everything else
- Nginx Proxy Manager – the reverse proxy that makes all your self-hosted services accessible with proper HTTPS, if you have not set it up already
- Uptime Kuma Monitoring – because your password manager going down without you knowing about it is not acceptable. Monitor it.
- Free Dynamic DNS with DuckDNS – if you do not own a domain, DuckDNS gives you a free subdomain that pairs perfectly with Vaultwarden for remote access
- Linux File Permissions Deep Dive – understanding who can read your Vaultwarden data directory matters. Permissions are security.
- Install Docker on Ubuntu 24.04 – the foundation everything here runs on, if you skipped it
Every service you move to your own infrastructure is one less place where a corporate breach, a policy change, or a ToS update can leave you locked out of your own data. Passwords are the most critical piece, and you have just taken that back.
Watch out for this: Back up your Vaultwarden data directory religiously. If you lose that SQLite database without a backup, you have lost every password. I run automated backups to a separate host nightly.
Key Takeaways
- Vaultwarden is a complete Bitwarden-compatible server that runs in a single Docker container on minimal hardware. All official Bitwarden clients work with it unmodified.
- HTTPS is mandatory, not optional. Password managers must encrypt in transit. Use a reverse proxy with Let’s Encrypt.
- Backups are the price of sovereignty. Self-hosting passwords without tested backups is worse than using a cloud provider. Automate it, store backups offsite, and test restores.
- Harden after setup: disable signups, secure or remove the admin panel, set rate limits, and consider fail2ban for brute-force protection.
- Family sharing works brilliantly. Organisations and collections give you granular, per-user access control over shared credentials.
- Self-hosting passwords is a responsibility, not just a project. Treat it with the same seriousness you would production infrastructure, because for your household, it is.
Related Guides
If you found this useful, these guides continue the journey:
- Docker Compose for Beginners — manage Vaultwarden alongside your other services
- Nginx Proxy Manager Setup — HTTPS is essential for a password manager
- Why Self-Host in 2026? — the case for owning your most sensitive data
- Self-Host Nextcloud — another essential sovereignty service
- Essential Docker Commands — manage and troubleshoot your containers
Before you expose any of this: the seven steps that decide whether a home lab survives contact with the internet, in the order they matter, are in How to Secure a Homelab Network in 2026.
Frequently Asked Questions
What port does Vaultwarden use by default?
The container listens on port 80 internally. You map that to whatever host port suits you, commonly something like 8080, and your reverse proxy forwards to it. Older guides also tell you to publish port 3012 for WebSocket notifications: that is obsolete. WebSockets have been served over the main HTTP port since Vaultwarden v1.29.0, and v1.31.0 removed port 3012 support altogether.
Do I need a reverse proxy for Vaultwarden?
In practice yes. The Bitwarden clients require HTTPS for anything that is not localhost, and Vaultwarden does not terminate TLS itself. Nginx Proxy Manager, Caddy and Traefik all work; Caddy needs the least configuration because it handles certificates automatically. Put the proxy and Vaultwarden on the same Docker network and forward to the container name so you never need to publish the port on the host.
Is Vaultwarden as secure as Bitwarden?
The cryptography is the same, because Vaultwarden implements the same API and the vault is encrypted client-side before it ever reaches the server. What differs is everything around it: you are now responsible for TLS, backups, patching and access control, where Bitwarden’s hosted service does that for you. Vaultwarden is not audited to the same standard as the official server either. Self-hosting moves the risk rather than removing it, and whether that is an improvement depends entirely on how well you run the steps in this guide.
Can I use the official Bitwarden apps with Vaultwarden?
Yes, and that is the main reason to use it. Every official Bitwarden client, on desktop, mobile and as a browser extension, works against a Vaultwarden server unchanged. You point the app at your own URL on the login screen using the self-hosted environment settings before you sign in. There is no separate Vaultwarden app to install.
How much RAM does Vaultwarden need?
Very little. It is written in Rust rather than running on .NET like the official server, and a small family instance typically sits well under 100 MB of RAM. It runs happily on a Raspberry Pi alongside other services, which is why it turns up in so many home labs where the official Bitwarden stack would be impractical.
How do I back up Vaultwarden?
Back up the data directory, which holds the SQLite database, the attachments, the RSA keys and the config. Stop the container or use the SQLite backup API rather than copying a live database file, or you risk a corrupt copy. Keep the backups encrypted and off the host, and restore one into a throwaway container to prove it works. A password manager backup you have never tested is the worst possible thing to discover is broken.
Should I expose Vaultwarden to the internet?
Only if you need vault access away from home, and only behind HTTPS with public signups disabled and the admin panel either locked down or turned off. If everyone who uses it is on your network or already on your VPN, do not publish it at all: reach it over Tailscale or WireGuard instead. That removes it from automated scanning entirely, which is the same reasoning as step 1 of the homelab security guide.
RTFM Apparel · printed in the UK

ReadTheManual is run, written and curated by Eric Lonsdale.
Eric has over 20 years of professional experience in IT infrastructure, cloud architecture, and cybersecurity, but started with PCs long before that.
He built his first machine from parts bought off tables at the local college campus, hoping they worked. He learned on BBC Micros and Atari units in the early 90s, and has built almost every PC he’s used between 1995 and now.
From helpdesk to infrastructure architect, Eric has worked across enterprise datacentres, Azure environments, and security operations. He’s managed teams, trained engineers, and spent two decades solving the problems this site teaches you to solve.
ReadTheManual exists because Eric believes the best way to learn IT is to build things, break things, and actually read the manual. Every guide on this site runs on infrastructure he owns and maintains.
Enjoyed this guide?
New articles on Linux, homelab, cloud, and automation every 2 days. No spam, unsubscribe anytime.






