Skip to main content

Why a reverse proxy is required

Hagaki binds to 0.0.0.0:8899 and has no built-in authentication, TLS, or rate limiting. You must not expose it directly to the internet. An Nginx reverse proxy handles:
  • TLS termination — serve HTTPS without modifying Hagaki
  • Security headers — add browser-level protections at the proxy layer
  • Response caching — cache rendered images so Hagaki only renders each card once
  • Access control — restrict access if needed without touching the application

Server block configuration

server {
  listen 80;
  server_name hagaki.yuli-bot.com;

  add_header X-Content-Type-Options nosniff;
  add_header X-Frame-Options SAMEORIGIN;
  add_header X-XSS-Protection "1; mode=block";

  location / {
    proxy_pass http://127.0.0.1:8899;
  }
}

Directive reference

DirectiveValuePurpose
listen 80Listens for HTTP on port 80
server_namehagaki.yuli-bot.comHostname this block responds to
proxy_passhttp://127.0.0.1:8899Forwards all requests to Hagaki

Security headers

HeaderValueEffect
X-Content-Type-OptionsnosniffPrevents browsers from MIME-sniffing the response type, reducing the risk of drive-by download attacks
X-Frame-OptionsSAMEORIGINBlocks the page from being embedded in an iframe on a different origin, preventing clickjacking
X-XSS-Protection1; mode=blockInstructs older browsers to block pages when a reflected XSS attack is detected
X-XSS-Protection is largely redundant in modern browsers, which have built-in XSS protections. It is included for compatibility with older clients.

Enabling the site

1

Create the config file

Save the server block above to /etc/nginx/sites-available/hagaki.
2

Create a symlink

sudo ln -s /etc/nginx/sites-available/hagaki /etc/nginx/sites-enabled/hagaki
3

Test the configuration

sudo nginx -t
Fix any reported errors before reloading.
4

Reload Nginx

sudo systemctl reload nginx

Caching rendered images

Hagaki renders are deterministic — the same request always produces the same image. You can use proxy_cache to serve cached renders directly from Nginx, bypassing Hagaki entirely on repeat requests. Add a cache zone in the http block of /etc/nginx/nginx.conf:
http {
  proxy_cache_path /var/cache/nginx/hagaki
    levels=1:2
    keys_zone=hagaki_cache:10m
    max_size=1g
    inactive=7d
    use_temp_path=off;

  # ... other http settings
}
Then enable caching in the location block:
location / {
  proxy_pass         http://127.0.0.1:8899;
  proxy_cache        hagaki_cache;
  proxy_cache_valid  200 7d;
  proxy_cache_use_stale error timeout updating;
  add_header         X-Cache-Status $upstream_cache_status;
}
The X-Cache-Status header will be HIT for cached responses and MISS for the first request. This makes it easy to verify caching is working during testing.
Create the cache directory before reloading Nginx:
sudo mkdir -p /var/cache/nginx/hagaki
sudo chown www-data:www-data /var/cache/nginx/hagaki

Build docs developers (and LLMs) love