en
SvelteKit Tor Hidden Service Deployment 2026
SvelteKit's small bundle sizes, fast server-side rendering, and flexible adapter system make it an excellent choice for Tor hidden service applications. Smaller bundles mean faster loading over Tor's limited bandwidth. This guide covers SvelteKit .onion deployment.
Need this done for your project?
We implement, you ship. Async, documented, done in days.
SvelteKit Adapter Selection for .onion
SvelteKit uses adapters to configure output format. For .onion deployment: adapter-node (server-side rendering with a Node.js server), adapter-static (fully static HTML output, no server required), and adapter-auto (auto-detects environment). Recommended for most .onion services: adapter-node provides full SSR, server-side data loading, and form actions. Configuration: in svelte.config.js: import adapter from '@sveltejs/adapter-node'; adapter({ out: 'build' }). The build/ directory contains the Node.js server entry point. Run with node build/index.js. Environment variables: set PORT, HOST (127.0.0.1 to bind locally only, never 0.0.0.0 for security), and ORIGIN (set to http://youraddress.onion for CSRF protection).
Static Adapter for Zero-Server .onion
For purely static .onion services (documentation, marketing, simple information sites): use @sveltejs/adapter-static. This generates pure HTML/CSS/JavaScript with no runtime server. Configuration: prerender.default = true in all pages, or configure specific pages for prerendering. The out/ directory contains complete HTML files. Serve with Nginx static configuration. Advantages: no Node.js process to maintain, fastest possible response times, simplest deployment. Limitations: no server-side user authentication, no real-time data (must use client-side fetching), and no form actions (must use JavaScript for form submission). For many information-focused .onion sites, static is the right choice.
SvelteKit Security and CSP for .onion
SvelteKit generates inline scripts and styles by default. For CSP (Content Security Policy): handle in hooks.server.ts (server-side hook that runs on every request). Use SvelteKit's built-in CSP support via svelte.config.js: kit.csp.directives. Example: { 'default-src': ['self'], 'script-src': ['self'], 'style-src': ['self', 'unsafe-inline'], 'img-src': ['self', 'data:'] }. SvelteKit's nonce-based CSP: use the csp.mode: 'hash' or 'nonce' option for CSP without unsafe-inline. CSRF protection: SvelteKit's form actions include built-in CSRF protection (Origin header checking). Set the ORIGIN environment variable to your .onion address for CSRF protection to work correctly.
Load Functions and Data Fetching on .onion
SvelteKit's +page.server.ts load functions run on the server before the page is rendered. For .onion services: fetch() in server-side load functions can access your database or backend services directly (they run on the server, not through Tor). Do NOT fetch from external URLs in server-side load functions (this reveals your server's IP to external services). For client-side load functions (+page.ts): these run in the browser (Tor Browser), so fetch requests go through Tor. External API calls from the client side are fine (they go through Tor automatically). Pattern for database data: always use server-side load functions for database queries. Never fetch your own database API from the client side (unnecessary round-trip through Tor when server-side is faster and simpler).
Deployment with PM2 and Nginx
PM2 manages the SvelteKit Node.js process: pm2 start build/index.js --name sveltekit-onion. PM2 ecosystem.config.js: module.exports = { apps: [{ name: 'sveltekit', script: 'build/index.js', env: { NODE_ENV: 'production', PORT: 3000, HOST: '127.0.0.1', ORIGIN: 'http://youraddress.onion' }, restart_delay: 5000, max_restarts: 10 }] }. Nginx reverse proxy: proxy_pass http://127.0.0.1:3000;, set proxy headers as for any Node.js app. Torrc: HiddenServicePort 80 127.0.0.1:YOUR_NGINX_PORT. Zero-downtime deployment: PM2's reload command (pm2 reload sveltekit) performs graceful reload (waits for existing connections to complete before restarting). Deploy script: build new version, copy to server, run PM2 reload. Active connections continue; new connections hit the new version.
Related Services
Why Anubiz Host
100% async — no calls, no meetings
Delivered in days, not weeks
Full documentation included
Production-grade from day one
Security-first approach
Post-delivery support included
Ready to get started?
Skip the research. Tell us what you need, and we'll scope it, implement it, and hand it back — fully documented and production-ready.