---
date: '2026-02-21T16:18:00+01:00'
draft: false
title: 'Server Setup'
---

First, decide where you want your Hister server to run, relative to your client(s).
There are three options:

- **On the same computer**: simplest, but limited to that machine (single device).
- **On the same local network**: still mostly simple, but limited to that network (roughly, only for devices connected to the same router&mdash;it won't work over 4G/5G/...!).
- **Over the Internet**: requires the most setup, but accessible from everywhere.

The first one is covered by the basic setup (just run `hister listen`), but the other two require some more consideration, and modifying the Hister server's config.

## Local Network

The [`server` configuration] needs to be edited to tell the Hister server to allow talking with other machines on the local network (usually, this means "connected to your router").

1. Edit the `address` and `base_url` fields:

   ```yaml
   server:
     address: '[::]:4433'
     base_url: http://localhost:4433
   ```

   (_Optionally_, if you want to listen on a specific network interface, append `%<interface_name>` after the closing bracket `]` in `address`.)

2. To apply those changes, close the Hister server if it was already running, and restart it.
   Check that you can access the Hister Web interface at <http://localhost:4433>.
   If not, replace `[::]` in `address` with `0.0.0.0`, and retry this step.

We now need to replace `localhost` with a location other machines can use to find this computer.
You can either use a **static IP**, if you know how to assign one to a computer; otherwise, you can use the computer's **hostname**, which may be a little more finicky and less reliable.

<details><summary>Static IP</summary>

Assign the Hister server's computer its permanent IP, then register it in `base_url`.
For example, for the IP `192.168.42.69`:

```yaml
base_url: http://192.168.42.69:4433
```

It is also possible to access the Web interface using the computer's hostname even if it has a static IP, which may be easier to remember; but placing the IP in the config should remain more reliable.

</details>
<details><summary>Hostname</summary>

This can be more finicky, because sharing hostnames between computers without some setup is sometimes broken on home networks because routers break them.
This can be less reliable, because if your computer's IP address may occasionally change while the server is up, which can cause short disruptions.

1. Obtain the computer's hostname:
   - **Linux**, **macOS**: you can run the `hostname` command in the terminal, or find the hostname somewhere in system settings.
   - **Windows**: TODO (note also that you may need to [enable network discovery](https://superuser.com/questions/1560557/can-access-shared-network-files-by-ip-but-not-by-host-name#answer-1560563) for your PC to announce its hostname).

2. Replace `localhost` in `base_url:` with the hostname \*suffixed by `.local`.
   For example, let's use my laptop's hostname `zonai-goat`, though it can be something like `DESKTOP-D9JCP0Q`.

   ```yaml
   server:
     address: '[::]:4433'
     base_url: http://zonai-goat.local:4433
   ```

3. Restart the Hister server, then try accessing the Hister Web interface (preferably from another device!) at the address specified in the `base_url` field.
   If your browser reports being unable to connect to the server, check your firewall settings.

   If the issue persists, try removing the `.local` part of the `base_url`, restart the server, and try again (don't forget to remove the `.local` part from your browser's address bar also!).

</details>

## Over the Internet

_Since this implies administration a system exposed to the Internet and **owning a domain name**, this section assumes more technical knowledge than the previous one._

Careful! **<mark>Security</mark>** considerations start rearing their head.
Hister transmits your entire browsing history, _with page contents_, to and from the server.
This is not something you want circulating unencrypted on the public Internet; therefore, we **strongly** recommend connecting to the server using HTTPS.

Hister's server does not support HTTPS itself, which is solved by using a [reverse proxy].
In particular, some, like [Caddy] or [Traefik], have built-in support for automatically requesting the required [TLS certificate].

1. Fill in the [`server` configuration] with your domain name and a loopback listen address:
   ```yaml
   server:
     address: 127.0.0.1:4433
     base_url: https://hister.example.com
   ```
2. (Re)start the Hister server to apply the change.
3. Set up your favourite reverse proxy. Here are some examples:

### Caddy

In your `Caddyfile`:

```
hister.example.com {
    reverse_proxy localhost:4433
}
```

Alternatively, if running Caddy solely for Hister:

```bash
caddy reverse-proxy --from hister.example.com --to localhost:4433
```

### Nginx

```nginx
# Make sure you have a good TLS configuration!
# https://ssl-config.mozilla.org/#server=nginx

# You will also need to point Nginx at your TLS certificate,
# https://nginx.org/en/docs/http/configuring_https_servers.html
# and likely also set up auto-renewal, assuming you're using Let's Encrypt.
# https://letsencrypt.org/docs/client-options/

server {
	server_name hister.example.com;
	listen 443 ssl; listen [::]:443 ssl;
	http2 on;
	listen 443 quic; listen [::]:443 quic;
	http3 on;
	add_header Alt-Svc 'h3=":443"; ma=86400; persist=1'; # Advertise HTTP/3 support.

	gzip off; # Prevents some security vulns on encrypted traffic.
	# Redirect HTTP reqs made on the HTTPS port into proper HTTPS reqs.
	error_page 497 =301 https://$host:$server_port$request_uri;

	location / {
		proxy_pass http://127.0.0.1:4433$request_uri;

		# More secure and performant than the default.
		proxy_http_version 1.1;

		# Uncomment this if you know what you're doing.
		# add_header Access-Control-Allow-Origin *;
		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_set_header        X-Scheme          $scheme;

		# Configuration necessary for the /search endpoint.
		proxy_set_header   Upgrade    $http_upgrade;
		proxy_set_header   Connection $hister_connection; # This variable is defined in a `map` below.
		proxy_read_timeout 86400;

		# Some pages are larger than the default of 1 MiB, causing `413` errors.
		# 100 MiB should be reasonably large, adjust to taste.
		client_max_body_size 100m;
	}
}
# Optionally: add an extra `server` block to redirect HTTP to HTTPS.
server {
	server_name hister.example.com;
	listen 80;
	listen [::]:80;
	# Redirect HTTP to HTTPS.
	return 301 https://$host$request_uri;
}
# This is used to upgrade WebSocket connections on the `/search` endpoint.
map $uri $hister_connection {
	/search upgrade;
	default close;
}
```

**Note**: if search doesn't work, there likely is a problem with WebSocket connections; troubleshooting info can be gathered from Nginx's `access.log` (tells you whether requests reached Nginx) and `error.log` (tells if you if any errors occurred _within_ Nginx).

## AppArmor Profile

If your Linux system uses AppArmor, you can confine Hister with the following profile.
Save it to `/etc/apparmor.d/hister`, then load it with `sudo apparmor_parser -r /etc/apparmor.d/hister`.

```
abi <abi/4.0>,

include <tunables/global>

@{hister_exe} = /usr/{local/,}bin/hister

profile hister @{hister_exe} {
  include <abstractions/base>
  include <abstractions/nameservice>
  include <abstractions/ssl_certs>
  include <abstractions/user-tmp>

  network inet dgram,
  network inet stream,
  network inet6 stream,

  unix (connect, send, receive, create) type=stream,

  @{HOME}/.config/chromium/Default/History r,
  @{HOME}/.config/hister{,/**} rwlk,
  @{HOME}/.mozilla/firefox/*.*/places.sqlite r,
  @{PROC}/sys/net/core/somaxconn r,
  @{hister_exe} rix,
  owner /proc/@{pid}/{cgroup,comm,cmdline,smaps,statm,stat,mountinfo,fdinfo/*} r,
}
```

**Note**: the paths above assume the default Hister data directory (`~/.config/hister`).
If you use a custom `app.directory`, add a corresponding `rwlk` rule for that path.
Browser history paths may also need adjustment depending on which profiles you use.

[`server` configuration]: configuration#server-section
[reverse proxy]: http://en.wikipedia.org/wiki/Reverse_proxy
[Caddy]: https://caddyserver.com/
[Traefik]: https://doc.traefik.io/traefik/getting-started/
[TLS certificate]: https://en.wikipedia.org/wiki/TLS_certificate
