Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/binary-person/rammerhead/llms.txt

Use this file to discover all available pages before exploring further.

All Rammerhead configuration lives in src/config.js. The file exports a single object whose properties control everything from which address the server binds to, to how sessions are stored and how JavaScript rewrites are cached. You rarely need to edit src/config.js directly — instead, create a config.js file in the project root and export only the properties you want to change. Rammerhead merges that file over the defaults automatically.

Override mechanism

At the bottom of src/config.js, Rammerhead checks for a root-level config.js and merges it in:
// src/config.js (last line)
if (fs.existsSync(path.join(__dirname, '../config.js'))) Object.assign(module.exports, require('../config'));
This means you can keep src/config.js untouched — making git pull conflict-free — while maintaining your own settings:
// config.js (project root — create this file)
module.exports = {
    bindingAddress: '0.0.0.0',
    port: 9000,
    password: 'my-secret-password',
    ssl: {
        key: require('fs').readFileSync('/etc/ssl/private/server.key'),
        cert: require('fs').readFileSync('/etc/ssl/certs/server.crt'),
    },
};
The DEVELOPMENT environment variable enables debug-level logging and an additional /garbageCollect endpoint. Set it with DEVELOPMENT=true node src/server.js or by placing DEVELOPMENT=true in a .env file at the project root (Rammerhead loads .env files automatically via dotenv-flow).

Hosting

bindingAddress
string
default:"127.0.0.1"
The local IP address the HTTP server binds to. Use '0.0.0.0' to listen on all interfaces, which is required when accepting connections from outside the local machine.
port
number
default:"8080"
The main port the proxy listens on. All session creation, management endpoints, and proxied traffic flow through this port.
crossDomainPort
number
default:"8081"
A second port used for cross-domain resource requests that hammerhead isolates to avoid CORS issues. Set to the same value as port if you want to use a single port; Rammerhead handles the overlap correctly.
publicDir
string | null
default:"path.join(__dirname, '../public')"
Path to a directory of static files served at the root of the proxy. Set to null to disable static file serving entirely.
enableWorkers
boolean
default:"os.cpus().length !== 1"
Enable multi-threaded mode using Node.js cluster. Defaults to true on machines with more than one CPU core. When enabled, a master process distributes connections across worker processes using sticky sessions so that each session always lands on the same worker.
workers
number
default:"os.cpus().length"
Number of worker processes to spawn when enableWorkers is true. Defaults to the number of logical CPU cores.
ssl
object | null
default:"null"
TLS configuration. Set to null to serve plain HTTP. To enable HTTPS, pass an object with key and cert buffers — the same shape accepted by Node’s https.createServer:
ssl: {
    key: fs.readFileSync('/path/to/server.key'),
    cert: fs.readFileSync('/path/to/server.crt'),
}
For more details see the Node.js HTTPS docs.
getServerInfo
function
A function that receives the incoming req object and returns an object describing how clients should construct proxy URLs. Use this when Rammerhead sits behind a reverse proxy and its public hostname or ports differ from bindingAddress/port.Default (hardcoded localhost):
getServerInfo: () => ({ hostname: 'localhost', port: 8080, crossDomainPort: 8081, protocol: 'http:' })
Dynamic example (reads the Host header, useful behind nginx or Cloudflare):
getServerInfo: (req) => {
    return {
        hostname: new URL('http://' + req.headers.host).hostname,
        port: 443,
        crossDomainPort: 8443,
        protocol: 'https:'
    };
}

Authentication

password
string | null
default:"'sharkie4life'"
Password required to call /newsession, /editsession, and /deletesession. Clients pass it as a pwd query parameter. Set to null to allow anyone to create sessions without a password.
The default password is publicly known. Always change it before deploying to a public server.

Sessions

disableLocalStorageSync
boolean
default:"false"
When false, Rammerhead synchronizes the proxied site’s localStorage with the session store so it persists across requests. Set to true if clients send very large localStorage payloads and memory usage becomes a concern.
restrictSessionToIP
boolean
default:"true"
When true, a session can only be used from the IP address that created it. This prevents session hijacking but breaks use cases where users legitimately change IP mid-session (e.g., mobile users switching between Wi-Fi and cellular).

JS caching

Rammerhead rewrites all JavaScript that passes through it. The rewritten output is cached so identical scripts are not reprocessed on every request. Two cache backends are available.
jsCache
RammerheadJSMemCache | RammerheadJSFileCache
The JS rewrite cache instance. The default is a RammerheadJSFileCache backed by the cache-js/ directory with a 5 GB limit and 50,000 item cap.Memory cache (faster, limited to available RAM):
const RammerheadJSMemCache = require('./src/classes/RammerheadJSMemCache.js');

// config.js (project root)
module.exports = {
    jsCache: new RammerheadJSMemCache(50 * 1024 * 1024), // 50 MB
};
Disk cache (default, recommended for most deployments):
const path = require('path');
const RammerheadJSFileCache = require('./src/classes/RammerheadJSFileCache.js');

// config.js (project root)
module.exports = {
    jsCache: new RammerheadJSFileCache(
        path.join(__dirname, 'cache-js'), // cache directory (must exist)
        5 * 1024 * 1024 * 1024,           // max size in bytes (5 GB)
        50000,                             // max number of cached items
        true                               // enable worker mode for multi-threading
    ),
};
Disk caching is not recommended on slow HDD storage. Use an SSD or switch to memory caching if disk I/O is a bottleneck.

HTTP/2

disableHttp2
boolean
default:"false"
When false, Rammerhead uses HTTP/2 for connections from the proxy to destination sites. Disabling HTTP/2 may reduce memory usage and connection errors, but can break sites that require an HTTP/2 handshake before upgrading to a WebSocket (such as web.whatsapp.com).

Header rewriting

stripClientHeaders
string[]
default:"[]"
A list of request header names to remove before forwarding the request to the destination. Use this to strip headers added by a reverse proxy (such as Cloudflare) that would expose the proxy’s infrastructure:
stripClientHeaders: [
    'cf-ipcountry',
    'cf-ray',
    'x-forwarded-proto',
    'cf-visitor',
    'cf-connecting-ip',
    'cdn-loop',
    'x-forwarded-for',
]
rewriteServerHeaders
object
default:"{}"
A map of response header names to new values. Set a header to null to delete it. Set it to a function to compute the new value from the original:
rewriteServerHeaders: {
    // Delete the header entirely
    'x-frame-options': null,

    // Modify the header value using the original
    'content-security-policy': (originalValue) => '',
}

Session store

The fileCacheSessionConfig object configures RammerheadSessionFileCache, which serializes sessions to disk and manages their lifecycle.
fileCacheSessionConfig.saveDirectory
string
default:"path.join(__dirname, '../sessions')"
Directory where session files are written. Each session is stored as a .rhfsession file named by its session ID. The directory must exist before the server starts.
fileCacheSessionConfig.cacheTimeout
number
default:"1200000"
Time in milliseconds a session stays in memory after its last use before being written to disk and evicted from the in-memory cache. Default is 20 minutes (1,200,000 ms).
fileCacheSessionConfig.cacheCheckInterval
number
default:"600000"
How often in milliseconds the server checks for sessions that have exceeded cacheTimeout and should be flushed to disk. Default is 10 minutes (600,000 ms).
fileCacheSessionConfig.deleteUnused
boolean
default:"true"
When true, sessions that were created but never used (their lastUsed timestamp equals their createdAt timestamp) are deleted instead of being written to disk when evicted from memory.
fileCacheSessionConfig.deleteCorruptedSessions
boolean
default:"true"
When true, session files that fail JSON parsing (which can happen if Node.js exits abruptly while writing a session) are automatically deleted on load.
fileCacheSessionConfig.staleCleanupOptions
object | null
Controls periodic deletion of old session files from disk. Set to null to disable stale cleanup entirely. The default configuration is:
staleCleanupOptions: {
    staleTimeout: 1000 * 60 * 60 * 24 * 3,  // delete if unused for 3 days
    maxToLive: null,                           // no absolute age limit
    staleCheckInterval: 1000 * 60 * 60 * 6,  // check every 6 hours
}
  • staleTimeout — sessions not accessed within this window (in ms) are deleted. Set to null to disable.
  • maxToLive — sessions older than this (in ms) are deleted regardless of activity. Set to null to disable.
  • staleCheckInterval — how often (in ms) the stale cleanup runs.

Logging

logLevel
string
default:"'info'"
Controls which log messages are emitted. Valid values from most to least verbose: 'debug', 'traffic', 'info', 'warn', 'error', and 'disabled' (suppresses all output). Setting a level emits messages at that level and all higher-priority levels.When the DEVELOPMENT environment variable is set, the default changes to 'debug'.
generatePrefix
function
A function that receives a log level string and returns the prefix prepended to every log line. Override to change the timestamp format or add custom fields:
generatePrefix: (level) => `[${new Date().toISOString()}] [${level.toUpperCase()}] `
getIP
function
default:"(req) => req.socket.remoteAddress"
Extracts the client IP from a request object. The default reads req.socket.remoteAddress, which is correct when clients connect directly. When Rammerhead is behind a reverse proxy, use the forwarded header instead:
getIP: (req) => (req.headers['x-forwarded-for'] || req.connection.remoteAddress || '').split(',')[0].trim()

Full example override

The following config.js placed in the project root illustrates a typical production setup — listening on all interfaces, using HTTPS, with a custom password and Cloudflare header stripping:
// config.js (project root)
const fs = require('fs');

module.exports = {
    bindingAddress: '0.0.0.0',
    port: 443,
    crossDomainPort: 8443,
    ssl: {
        key: fs.readFileSync('/etc/ssl/private/server.key'),
        cert: fs.readFileSync('/etc/ssl/certs/server.crt'),
    },
    getServerInfo: (req) => ({
        hostname: new URL('http://' + req.headers.host).hostname,
        port: 443,
        crossDomainPort: 8443,
        protocol: 'https:',
    }),
    password: 'replace-with-a-strong-password',
    stripClientHeaders: [
        'cf-ipcountry',
        'cf-ray',
        'x-forwarded-proto',
        'cf-visitor',
        'cf-connecting-ip',
        'cdn-loop',
        'x-forwarded-for',
    ],
    rewriteServerHeaders: {
        'x-frame-options': null,
    },
    logLevel: 'warn',
};

Build docs developers (and LLMs) love