Serve Frequently-Used Files (Resume/CV) on Your VPS with One Link (NPM + Docker Compose)

Goal: Host a tiny “files corner” (e.g., resume.pdf, cv.pdf, slides, one-pagers) on your domain, opening inline in the browser over HTTPS, with minimal setup.

  • Spin up a tiny Nginx container that serves a folder of files.
  • Force PDFs to embed rather than download.
  • Put it behind Nginx Proxy Manager (NPM) for a clean HTTPS link like https://files.your-domain.com/resume.pdf.

Prerequisites

  • VPS with Docker + Docker Compose.
  • Nginx Proxy Manager (NPM) running.
  • A subdomain (e.g., files.your-domain.com) pointing to your VPS IP.

Step 1 — Create a folder and copy your files

sudo mkdir -p /opt/pdf-pub
# Put all frequently-used files here:
sudo cp /path/to/resume.pdf /opt/pdf-pub/
sudo cp /path/to/cv.pdf /opt/pdf-pub/
# ...slides.pdf, profile-onepager.pdf, etc.

(Keep filenames stable so your links don’t change.)


Step 2 — Minimal Nginx config (inline PDFs)

Create /opt/pdf-pub/default.conf:

server {
  listen 80;
  server_name _;

  root /usr/share/nginx/html;
  index index.html;

  # Force PDFs to open inline (not download)
  location ~* \.pdf$ {
    add_header Content-Disposition "inline" always;
    try_files $uri =404;
  }

  # Static file serving (no directory listing by default)
  location / {
    try_files $uri $uri/ =404;
  }
}
Optional: simple index page so people can see your file list.
Create /opt/pdf-pub/index.html (very minimal):

Or enable directory listing by changing the last location block to:

Step 3 — Docker Compose

Create /opt/pdf-pub/docker-compose.yml:

services:
  pdf-serve:
    image: nginx:alpine
    container_name: pdf-serve
    restart: unless-stopped
    ports:
      - "8082:80"              # host 8082 -> container 80
    volumes:
      - /opt/pdf-pub:/usr/share/nginx/html:ro
      - /opt/pdf-pub/default.conf:/etc/nginx/conf.d/default.conf:ro

Start:

cd /opt/pdf-pub
docker compose up -d

Quick test: http://<SERVER_IP>:8082/resume.pdf


Step 4 — Put it behind NPM for HTTPS

Subdomain (recommended):

  1. NPM → Proxy HostsAdd Proxy Host
  2. Domain Names: files.your-domain.com
  3. Forward Hostname / IP: 127.0.0.1
  4. Forward Port: 8082
  5. Block Common Exploits: ✓
  6. SSL → Request Let’s Encrypt cert (Force SSL ✓, HTTP/2 ✓)
  7. Save.

Now your evergreen links are:

  • https://files.your-domain.com/resume.pdf
  • https://files.your-domain.com/cv.pdf

(Drop updated files into /opt/pdf-pub/ with the same names to “replace in place.”)


Nice extras (optional)

  • Short links for business cards/QRs:
    Create NPM Proxy Host resume.your-domain.com → forward to 127.0.0.1:8082 with Custom Location /Rewrite to /resume.pdf. Then share https://resume.your-domain.com.
  • Basic auth for private files:
    In NPM → Access Lists, create a user and attach it to your proxy host.
  • Content types:
    Nginx serves common types by default; this setup also works for .png, .jpg, .zip, .docx, etc. (Only PDFs get the inline header.)
  • Zero-downtime updates:
    Replace files in /opt/pdf-pub/ directly—no container restart needed.

Cache control:
For PDFs you update often but want instant refresh, add in location ~* \.pdf$:

add_header Cache-Control "no-store" always;

Or use versioned filenames like resume_v2025.pdf and keep a permanent resume.pdf that you overwrite.


Troubleshooting

  • Downloads instead of inline: Confirm the Content-Disposition: inline block and clear your browser cache.
  • 404: Check filename case and path. Test http://IP:8082/<file> before NPM.
  • HTTPS/cert issues: Ensure DNS A/AAAA records point to the VPS, then re-issue in NPM.

Why this is perfect for resumes/CVs

  • Stable, memorable links you can put on LinkedIn, business cards, or email signatures.
  • Instant updates: overwrite resume.pdf and everyone gets the latest version.
  • Minimal footprint: tiny Nginx container + NPM TLS—nothing heavy, no app frameworks.

You now have a clean, lightweight “files corner” for your frequently used docs—especially your resume/CV—served over HTTPS and always just one link away.