Find where your data lives
In this guide you look at the three places Hatamoto keeps its state: the Postgres database, the media folder and the data directory. At the end you know what each one holds, which of them you must back up, and which you can lose without harm.
Before you start
- A shell on the server, with the service's settings loaded so
DATABASE_URLis set. See how Hatamoto is put together shows how, in step 1. - The
psqlclient, version 16 or newer, on the server. - The paths from your deployment. This guide uses the systemd layout: data directory
/opt/hatamoto/data(HATAMOTO_DATA) and media/opt/hatamoto/uploads(MEDIA_UPLOAD_DIR). With Docker, the data directory is/dataand media are in/app/uploads, each on its own Docker volume.
Everything here only reads. Nothing you run changes the site.
Steps
- Connect to the database with the same address the server uses:
psql "$DATABASE_URL" - List Hatamoto's tables. Every table the server owns starts with
hatamoto_:\dt hatamoto_*You see about 55 tables. Some are monthly parts of one larger table, such as
hatamoto_agent_hits_2026_11, which holds the visits of AI crawlers for that month. One more table,goose_db_version, records which migrations have run: the steps that update the database structure to match each new version. - See your content types. Hatamoto has no separate table for pages or posts. Each content type (the kind of content, which decides its fields and its address) is one row here:
SELECT slug, name, is_builtin FROM hatamoto_entity_schemas ORDER BY slug;slug | name | is_builtin ------------+------------+------------ block | Block | t page | Page | t person | Person | t post | Post | t theme_part | Theme part | tA fresh site has these five built-in types. Types you add in the admin appear here too, with
is_builtinset tof. - Count your content. Every page, post, person and other item is a row in one table,
hatamoto_entities, with its fields in a JSON column:SELECT s.slug AS type, e.status, count(*) FROM hatamoto_entities e JOIN hatamoto_entity_schemas s ON s.id = e.schema_id GROUP BY 1, 2 ORDER BY 1, 2;type | status | count ------+-----------+------- page | published | 1Only
publishedrows are visible on the site. Drafts, scheduled and archived items stay here, out of sight. - Look for plugin data. A plugin that stores data gets its own schema, named
plugin_<name>, so its tables never mix with the server's:\dnOn a site without such plugins you see only
public. - Leave
psql, so the next commands run in your shell again:\q - List the media folder. Uploaded images and files are stored here, not in the database. The database keeps only a record of each file (name, size, alt text):
ls /opt/hatamoto/uploads | head - List the data directory:
ls -la /opt/hatamoto/dataAmong other things it holds the server secret, a long random value the server uses to sign links and protect stored credentials. It must stay the same across restarts. What you may find there:
Folder or file Holds If you lose it secrets/secrets.envthe server secret, created on first start when you did not set HATAMOTO_SECRETtheme preview links and stored credentials, such as the captcha secret, stop working cache/wasmcompiled plugins nothing: the server rebuilds it releasesthe versions the supervisor (the process that starts the server and switches to a new version after an update) can switch between, and its state the next update downloads again; you cannot roll back without it backupsone database copy, pre-<version>.dump, taken before each updateonly that copy install_ida random id, kept on this machine, so that not every site gets an update at the same moment a new one is made, and your turn for updates may move If you set
HATAMOTO_SECRETin the settings file, it is never written to disk, and nosecrets.envis created.
Check it worked
You can now name the three things to back up and where they are:
| What | Where | How |
|---|---|---|
| Content, settings, users, installed plugins and themes | Postgres | pg_dump |
| Uploaded media | MEDIA_UPLOAD_DIR | copy the folder |
| Server secret | HATAMOTO_SECRET in your settings file, or secrets/secrets.env | keep a copy with your settings |
Themes and plugins you installed are stored inside the database, so the database backup covers them. The built-in default theme is part of the program itself.
If \dt hatamoto_* prints Did not find any relation, you connected to a different database than the server. Check that DATABASE_URL in your shell matches the settings file.
For a full backup routine, follow Backups. Every table and column is described on Data model.