This guide provides a practical security baseline for institutions managing an internet-accessible production deployment. It covers host security, TLS/HTTPS, Django security settings, and ongoing operations.
Recommended Background Reading
Step 1: Harden the Host
Make sure to configure a firewall before exposing Specify to the public internet.
- Apply all outstanding operating system updates and reboot if required.
- Disable password authentication for SSH in favor of SSH keys.
- Configure a local firewall to strictly limit inbound traffic.
- Enable automatic security patches for the host OS where possible.
- Ensure system time is synchronized using NTP (
chronyorsystemd-timesyncd).
Example: Host Firewall Setup (Ubuntu with UFW)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status
Step 2: Choose and Prepare Your Compose Scenario
Pick the deployment strategy that matches your institutional scale. See this guide for access to these deployment schemes:
all-in-one: Best for simpler, single-instance initial deployments.specifycloud: Production-style multi-instance template approach.
Action Items
- Copy or edit your scenario files (
docker-compose.yml,specify.env, and yournginx.conftemplates). - Ensure you use persistent, named volumes for both your database data and runtime web assets.
- Remove any unused service definitions from your composition files.
[!warning] Database Security
Never publish your MariaDB container network port (3306) to the host’s public network interface. Keep your database isolated on the internal container network.
Step 3: Configure DNS and TLS (HTTPS)
3.1 DNS Entry
Create an A/AAAA or CNAME record with your DNS provider pointing your public hostname to your server’s public IP address:
specify.yourinstitution.edu → Your Public IP
3.2 TLS Certificates
- Public Deployments: Use automated Let’s Encrypt certificates via certbot.
- Internal/Institutional Deployments: Use certificates generated by your organization’s internal PKI.
3.3 Reverse Proxy Configuration
Your reverse proxy (nginx) handles SSL/TLS termination, routes static assets, and proxies application traffic. It should be configured to force HTTPS and inject security headers.
You can review the default nginx.conf files in the docker-compositions repository once you have been granted access.
Step 4: Lock Down App-Level Host and Origin Settings
Modify the environment variables inside your specify.env to lock down Django’s security middleware:
ALLOWED_HOSTS=specify.yourinstitution.edu
CSRF_TRUSTED_ORIGINS=https://specify.yourinstitution.edu
[!danger] Avoid Wildcards
Do not leave permissive defaults like*,http://*, orhttps://*in a production environment. Doing so exposes your application to HTTP Host Header injections and Cross-Site Request Forgery (CSRF) vulnerabilities.
Additional Verification Checks
- Confirm that
DEBUG=Falseis set in production. - Generate a unique, long, random string for your application
SECRET_KEY.
Step 5: Protect Data Services & Internal Networking
- Network Isolation: Keep MariaDB, Celery, and Redis/Memcached on dedicated internal networks within your container runtime.
- Encrypted Backups: Encrypt all database dumps and asset backups both during transit and while at rest.
Step 6: Start and Validate the Deployment
Launching the Stack
Docker Compose:
cd docker/all-in-one
docker compose up -d
docker compose ps
docker compose logs -f
Podman Compose:
cd podman/all-in-one
podman-compose up -d
podman-compose ps
podman-compose logs -f
Validation Checklist
- Navigating to
http://specify.yourinstitution.educorrectly redirects tohttps://specify.yourinstitution.edu. - The web browser displays a valid, trusted TLS certificate padlock icon with no warnings.
- Core workflows (logging in, running queries, viewing records and attachments) operate cleanly over HTTPS.
- An external port scan confirms port
3306is completely inaccessible from outside the host.
Ongoing Security Operations
Set an operational maintenance routine from day one:
- Patching Schedules: Apply host operating system security updates monthly. Track tagged Specify 7 repository releases on GitHub or in Announcements & News for software and security updates.
- Backup Management: Automate daily database and asset snapshots.
- Access Control: Enforce the principle of least privilege for server access and use Multi-Factor Authentication (MFA) wherever possible.
Common Mistakes to Avoid
Leaving ALLOWED_HOSTS=*active in production.
Mapping container database ports to public host interfaces.
Relying on unencrypted HTTP connections for authentication.
Neglecting to set up automated certificate renewals.
Questions?
If your deployment runs into issues or encounters environmental errors, please grab your container logs and create a thread in our Get Help category.
Be sure to include:
- Your deployment framework (
DockerorPodman). - Your sanitized configuration files (
docker-compose.yml, proxy files). - The exact error trace from your application container logs.