This repository has a Dockerfile
and instructions for running prerender on
Dokku. You can easily enable official plugins (including a fixed version of blockRequests
) and
our prerender-plugin-fscache. It also comes with
pm2 configured, so the server keeps on even if an unhandled exception occurs.
Note that pre-rendering is NOT the same as server-side rendering: pre-rendering just helps you get better SEO by serving a pre-rendered HTML version with data filled in, but it's not supposed to replace the user experience in the browser. To make it work you'll need:
- A deployed prerender (this repository will help you deploy an instance to Dokku)
- Change your Web server configuration to serve static files to regular users but reverse proxy to your prerender instance when the user-agent is from a search engine or social media robot. If you're serving your frontend using nginx, see Configuring Nginx for an example.
Run on your Dokku server:
# Change these variables as needed
ADMIN_EMAIL="admin@example.net"
ALLOWED_DOMAINS="example.net" # Change if needed (like has other domains/subdomains)
APP_DOMAIN="prerender.example.net"
APP_NAME="myprerender"
BROWSER_TRY_RESTART_PERIOD="3600000"
CACHE_PATH="/var/cache/prerender" # Data path inside container for caching
CACHE_STATUS_CODES="200,301,302,303,304,307,308,404" # Status codes where cache works (only GET requests are cached)
CACHE_TTL="86400" # Cache time-to-live (in seconds)
ENABLED_PLUGINS="addMetaTags,blockResources,browserForceRestart,fscache,removeScriptTags,whitelist"
PRERENDER_LOG_REQUESTS="false" # Prerender is too noisy (enabling it is useful for debugging)
STORAGE_PATH="/var/lib/dokku/data/storage/$APP_NAME" # Data path on host machine for caching
dokku apps:create $APP_NAME
dokku domains:set $APP_NAME $APP_DOMAIN
dokku storage:ensure-directory --chown heroku $APP_NAME
dokku storage:mount $APP_NAME "$STORAGE_PATH:$CACHE_PATH"
dokku letsencrypt:set $APP_NAME email $ADMIN_EMAIL
# Now, let's go to the prerender/plugin-specific env vars:
dokku config:set --no-restart $APP_NAME ALLOWED_DOMAINS=$ALLOWED_DOMAINS # Only if you'd like to enable domain allow list
dokku config:set --no-restart $APP_NAME BROWSER_TRY_RESTART_PERIOD=$BROWSER_TRY_RESTART_PERIOD
dokku config:set --no-restart $APP_NAME CACHE_PATH=$CACHE_PATH # Only if you'd like to enable cache
dokku config:set --no-restart $APP_NAME CACHE_STATUS_CODES=$CACHE_STATUS_CODES
dokku config:set --no-restart $APP_NAME CACHE_TTL=$CACHE_TTL # Only if you'd like to enable cache
dokku config:set --no-restart $APP_NAME ENABLED_PLUGINS=$ENABLED_PLUGINS
dokku config:set --no-restart $APP_NAME PAGE_LOAD_TIMEOUT=30000
dokku config:set --no-restart $APP_NAME PRERENDER_LOG_REQUESTS=$PRERENDER_LOG_REQUESTS
Note that prerender reads some environment variables and you can set them with
dokku config:set $APP_NAME VAR=value
. See the list of plugins in the section Available Plugins and the file system cache plugin environment variables in Cache settings.
Now, clone this repository on your local machine, add the Dokku host as a remote and push to it:
git clone https://github.com/PythonicCafe/dokku-prerender.git
cd dokku-prerender
git remote add dokku dokku@<server-ip>:<app-name>
git push dokku main
Finally, generate the SSL certificate using Let's Encrypt and scale the number of containers if needed:
dokku letsencrypt:enable $APP_NAME
dokku ps:scale $APP_NAME web=2
cp env.example .env
make start
The command below will build the container image using docker compose
, configure directory permissions for cache
volume and run the container.
Now, access http://localhost:3000/https://example.net/.
addMetaTags
: Addx-prerender-render-id
andx-prerender-render-at
meta tags with debugging infobasicAuth
: Requires HTTP auth (usingBASIC_AUTH_USERNAME
andBASIC_AUTH_PASSWORD
)blacklist
: Block domains fromBLACKLISTED_DOMAINS
blockResources
: Ignore requests of images, fonts and to some domains (like Google Analytics)browserForceRestart
: Restart browser afterBROWSER_FORCE_RESTART_PERIOD
milliseconds (default:3600000
)fscache
: cache GET responses on filesystem. Only some status codes (CACHE_STATUS_CODES
) are cached. Files are stored atCACHE_PATH
and expires afterCACHE_TIMEOUT
secondshttpHeaders
: Transformprerender-status-code
andprerender-header
meta tags into response headersremoveScriptTags
: Remove<script>
(except for type='application/ld+json') and<link rel="import">
tagssendPrerenderHeader
: AddX-Prerender: 1
to request headerswhitelist
: Render only pages from domains inALLOWED_DOMAINS
The directory utils
has some useful Python scripts:
warmup_cache.py
: from a prerender instance URL and a text file with URLs, this script will request all these URLs to the prerender server, so you end up with all of them cached.refresh_facebook_cache.py
: scrape Facebook Share Debugger to refresh URLs from a text file. Will help creating previews when people share your links.
If you're serving your static file on Nginx, you'll need to configure it to proxy the robot requests through your prerender instance. Check the file nginx-default.conf for an example (I curated a list of 68 robots, including search engines, social media and SEO metrics).