Introduction
Your browser’s new tab page is prime real estate — and most people squander it. The default experience from Chrome or Firefox hands you a search bar, a row of recently visited thumbnails, and a fistful of news you didn’t ask for. Jump Startpage takes a completely different approach. It’s a clean, self-hosted browser start page that gives you a curated bookmark grid, a live clock, and a configurable search bar, all served straight from your own VPS. No third-party data collection. No clutter. Just your links, your way.
Self-hosting Jump means you stay in the driver’s seat. You control what shows up, what gets updated and when access is granted. This guide walks you through deploying Jump on a VPS using Docker, Nginx as a reverse proxy and a free Let’s Encrypt SSL certificate. By the end, you’ll have a snappy, private start page running at your own domain.
What Is Jump Startpage?
Jump is an open-source, self-hosted browser start page built by developer Dale Davies. Think of it as a dashboard for your browser — one you actually designed. It’s lightweight, written in PHP and served via Docker, which makes deployment straightforward even if you’ve never touched a PHP server in your life.
Out of the box, Jump offers a solid feature set:
- Bookmark grid — Add any number of sites organized by custom tags for quick filtering.
- Live clock — Displays the current time with optional 12-hour or 24-hour format.
- Configurable search bar — Point it at Google, DuckDuckGo, Brave Search or any search engine you prefer.
- Site status checking — Jump can ping your bookmarked sites and visually flag any that go offline.
- Custom backgrounds — Drop your own image into a folder and Jump picks it up automatically.
- Weather widget — Optional integration for current conditions using a free weather API.
Everything is configured through a simple JSON file and environment variables. No database. No complicated admin panel. That simplicity is exactly what makes it so appealing for a personal or team deployment.
Prerequisites
Before diving in, make sure your VPS meets the hardware requirements below. Jump is genuinely lightweight so even a modest server handles it with ease.
| Requirement | Minimum | Recommended |
|---|---|---|
| Operating System | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
| RAM | 512 MB | 1 GB |
| CPU | 1 vCPU | 1 vCPU |
| Disk Space | 5 GB | 10 GB |
| Network | Public IPv4 address | Public IPv4 address |
You’ll also need the following in place before starting:
- A domain name with an A record pointed at your VPS IP address.
- Root or sudo access on the server.
- Ports 80 and 443 accessible from the public internet.
How to Install Jump Startpage on a VPS
Step 1: Update the Server
Always start with a clean slate. Run a full package update before installing anything new — this avoids dependency conflicts and patches any known security issues that ship with a fresh VPS image.
sudo apt update && sudo apt upgrade -y
Reboot if a kernel update was included:
sudo reboot
Wait about 30 seconds then reconnect via SSH before continuing.
Step 2: Install Docker Engine
Ubuntu’s default package repositories include an older version of Docker called docker.io. Don’t use it. Install Docker Engine directly from Docker’s official repository to get the current stable release.
First, install the required dependencies:
sudo apt install -y ca-certificates curl gnupg
Add Docker’s official GPG key:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
Add the Docker repository to your apt sources:
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Now install Docker Engine and the Compose plugin:
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Confirm Docker is running:
sudo docker run hello-world
You should see a “Hello from Docker!” message confirming a successful install. Next, add your user to the Docker group so you can run Docker commands without sudo:
sudo usermod -aG docker $USER
newgrp docker
Step 3: Create the Project Directory
Keeping your Jump files organized in one place makes updates and backups much simpler. Create a dedicated directory and step into it:
mkdir -p /opt/jump/{config,backgrounds,icons}
cd /opt/jump
The three subdirectories each serve a specific purpose:
- config — Holds your
sites.jsonbookmark configuration file. - backgrounds — Drop any custom background images here and Jump will cycle through them.
- icons — Store custom site icons here if you want to override the defaults.
Step 4: Configure Docker Compose
Create the Docker Compose file that defines the Jump container and its settings:
nano /opt/jump/docker-compose.yml
Paste in the following configuration:
services:
jump:
image: daledavies/jump:latest
container_name: jump
restart: unless-stopped
ports:
- "127.0.0.1:8080:80"
volumes:
- ./config:/srv/jumpapp/config
- ./backgrounds:/srv/jumpapp/backgrounds
- ./icons:/srv/jumpapp/icons
environment:
- SITENAME=My Startpage
- SHOWCLOCK=true
- AMPM=false
- METRICTEMP=true
- SHOWGREETING=true
- GREATINGNAME=World
- CHECKSTATUS=true
- STATUSCACHE=5
- SHOWSEARCH=true
- SEARCHURL=https://www.google.com/search?q=
- OPENLINKSNEWTAB=true
- CACHEBYPASS=0
A few things worth noting about this configuration:
- The port binding
127.0.0.1:8080:80restricts Jump to the loopback interface. Nginx handles all public traffic — the container itself is never directly reachable from the internet. - Set
AMPM=trueif you prefer a 12-hour clock format. - Set
METRICTEMP=falseto switch weather readings to Fahrenheit. - Replace the
SEARCHURLvalue with your preferred search engine’s query URL (e.g.,https://search.brave.com/search?q=for Brave Search). - Change
SITENAMEto whatever title you want displayed in the browser tab.
Save and close the file with Ctrl+X, then Y and Enter.
Before publishing, verify you’re using the current image tag on Docker Hub. The latest tag tracks the most recent stable release but pinning to a specific version tag gives you predictable behavior across updates.
Step 5: Create Your Sites Configuration
Jump reads your bookmarks from a sites.json file inside the config directory. Create that file now:
nano /opt/jump/config/sites.json
Add your bookmarks using the structure below. Each entry is a JSON object with a name, URL, optional description, and one or more tags for filtering:
[
{
"name": "Google",
"url": "https://www.google.com",
"description": "Search the web",
"icon": "",
"nofollow": false,
"tags": ["search"]
},
{
"name": "GitHub",
"url": "https://github.com",
"description": "Code repositories",
"icon": "",
"nofollow": false,
"tags": ["dev"]
},
{
"name": "YouTube",
"url": "https://www.youtube.com",
"description": "Video platform",
"icon": "",
"nofollow": false,
"tags": ["media"]
},
{
"name": "Hacker News",
"url": "https://news.ycombinator.com",
"description": "Tech news and discussion",
"icon": "",
"nofollow": false,
"tags": ["news", "dev"]
}
]
The tags array is what makes the filtering feature useful. Assign meaningful category names and Jump will let you click a tag to show only the matching bookmarks. A site can belong to multiple tags simultaneously.
The nofollow field controls whether Jump adds a rel="nofollow" attribute to the link. Set it to true for any links you’d rather not pass SEO authority to. Save the file when you’re satisfied with your initial set of bookmarks.
Step 6: Launch the Jump Container
With the configuration in place, start the container:
cd /opt/jump
docker compose up -d
Docker pulls the Jump image and starts the container in detached mode. Verify it’s running:
docker compose ps
The container’s status should read Up. Run a quick connectivity check to confirm the application responds on the loopback port:
curl -I http://127.0.0.1:8080
A 200 OK response means Jump is up and serving traffic. If you see a connection error instead, jump to the troubleshooting section below before continuing.
Step 7: Install Nginx
Nginx acts as the public-facing gateway, forwarding browser requests to Jump running on the loopback interface. Install it from the Ubuntu repositories:
sudo apt install -y nginx
Enable and start Nginx:
sudo systemctl enable nginx
sudo systemctl start nginx
Step 8: Configure Nginx as a Reverse Proxy
Create a new Nginx server block for your Jump domain. Replace startpage.yourdomain.com with your actual domain throughout this step:
sudo nano /etc/nginx/sites-available/jump
Paste in this configuration:
server {
listen 80;
listen [::]:80;
server_name startpage.yourdomain.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
}
}
Save the file and enable the site by creating a symlink:
sudo ln -s /etc/nginx/sites-available/jump /etc/nginx/sites-enabled/
sudo nginx -t
The nginx -t command tests the configuration for syntax errors. If the output says test is successful you’re good to reload:
sudo systemctl reload nginx
Step 9: Configure the Firewall
UFW (Uncomplicated Firewall) ships with Ubuntu. If it’s not already active, enable it now. This configuration allows SSH, HTTP and HTTPS while blocking everything else:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
Confirm the rules are applied:
sudo ufw status
You should see OpenSSH and Nginx Full listed as allowed. The firewall ensures port 8080 stays inaccessible from the public internet — only Nginx exposes Jump to the outside world.
Step 10: Enable SSL with Let’s Encrypt
A start page without HTTPS is a start page with a browser warning banner. Fix that with a free certificate from Let’s Encrypt via Certbot. Install it now:
sudo apt install -y certbot python3-certbot-nginx
Request your certificate. Replace the domain and email with your actual values:
sudo certbot --nginx -d startpage.yourdomain.com --email [email protected] --agree-tos --no-eff-email
Certbot automatically modifies your Nginx configuration to handle the HTTPS redirect and certificate renewal. Confirm that auto-renewal is working:
sudo certbot renew --dry-run
With a successful dry run, Let’s Encrypt will silently renew your certificate every 60-90 days without any manual intervention. Open https://startpage.yourdomain.com in your browser and you should see your Jump start page, complete with your bookmarks and a padlock in the address bar.
How to Update Jump Startpage
Keeping Jump current is a two-minute task. Pull the latest image and recreate the container:
cd /opt/jump
docker compose pull
docker compose up -d
Docker Compose detects the updated image and replaces the running container with zero manual cleanup required. Your configuration files in /opt/jump/config, /opt/jump/backgrounds and /opt/jump/icons persist across updates because they live on the host filesystem, not inside the container.
To verify you’re running the new version, check the container logs for the startup output:
docker compose logs --tail=20 jump
Before any update, take a moment to review the Jump release notes on GitHub. Major version bumps occasionally introduce changes to the configuration format that require a small adjustment to your sites.json or environment variables.
Troubleshooting Jump Startpage
Container Won’t Start
If docker compose ps shows the Jump container in an Exit or Restarting state, the first place to look is the container logs:
docker compose logs jump
Look for PHP errors or volume permission complaints. The most common culprit at startup is a malformed sites.json file. Validate your JSON syntax using an online linter or the command-line tool jq:
cat /opt/jump/config/sites.json | jq .
A parse error from jq pinpoints exactly where the JSON breaks. Fix it, then restart the container:
docker compose restart jump
Nginx Returns a 502 Bad Gateway
A 502 means Nginx is running but can’t reach the Jump container on port 8080. Confirm the container is actually up:
docker compose ps
curl -I http://127.0.0.1:8080
If the curl fails, the container itself is the problem — check the logs as described above. If the curl succeeds but Nginx still returns 502, verify the proxy pass address in /etc/nginx/sites-available/jump exactly matches the port in your docker-compose.yml. A mismatch between the two files is the usual source of this mismatch. After correcting any discrepancy, reload Nginx:
sudo nginx -t && sudo systemctl reload nginx
SSL Certificate Fails to Issue
Certbot verifies domain ownership by serving a challenge file over HTTP on port 80. If port 80 is blocked by your firewall or your DNS A record hasn’t fully propagated yet, the challenge fails. Check that UFW is allowing HTTP traffic:
sudo ufw status | grep -i nginx
Both Nginx Full or Nginx HTTP and Nginx HTTPS should appear as ALLOW. Then verify your DNS resolution looks correct from an external vantage point using a tool like dnschecker.org. DNS propagation can take up to 48 hours after making a change — though it usually completes within an hour. Once both checks pass, rerun the Certbot command.
Changes to sites.json Don’t Appear
Jump caches configuration on startup. If you edit sites.json and refresh the browser without seeing the change, the cache is the reason. Force a cache bypass by setting the CACHEBYPASS environment variable to any non-zero value in your docker-compose.yml and restarting the container:
cd /opt/jump
docker compose restart jump
In a production setup, reset CACHEBYPASS back to 0 after confirming your changes look correct. Leaving cache bypass enabled long-term forces Jump to re-read the configuration on every page load, which is unnecessary overhead.
Volume Permission Errors
If the container logs show Permission denied errors when trying to read the config, backgrounds or icons directories, the host directories may have restrictive ownership. The Jump container process runs as a non-root user internally. Grant world-readable permissions to the mounted directories:
sudo chmod -R 755 /opt/jump/config /opt/jump/backgrounds /opt/jump/icons
Protect the sites.json file itself from other system users while keeping it readable by the container:
sudo chmod 644 /opt/jump/config/sites.json
Then restart the container and re-check the logs:
docker compose restart jump
docker compose logs --tail=20 jump
What to Build Next
Your Jump Startpage is live — but it’s just the beginning of what you can build on this VPS. A few natural next steps worth exploring:
- Add a weather widget — Jump supports weather display via the OpenWeatherMap API. Sign up for a free API key, add the relevant environment variables to your
docker-compose.ymland your start page gains a live weather card. - Deploy Uptime Kuma alongside Jump — Uptime Kuma is a self-hosted monitoring dashboard that tracks the availability of all your bookmarked sites. Pair it with Jump’s built-in status checking for a comprehensive uptime view in one place.
- Set up a private link shortener — Tools like YOURLS or Shlink let you create memorable short URLs that point to any of your bookmarked destinations — handy for sharing with teammates.
- Automate backups of your config directory — Set up a cron job to tar your
/opt/jump/configdirectory and push it to object storage or a remote server so a misconfigured update never loses your bookmark list.
Conclusion
Setting up Jump Startpage on a VPS with Docker takes under 30 minutes and the result is genuinely better than any browser default. You get a fast, private, self-hosted start page that opens instantly, shows exactly what you need and never phones home. Every bookmark, every tag, every background image is yours. That’s the whole point of self-hosting — and Jump delivers it without any of the complexity you’d normally associate with running your own web service. Update it in two commands. Customize it with a text editor. Back it up with a single folder. Simple tools done right.


