{"result":{"depiction_url":null,"edges":{"hasreference":{"objects":[{"created":"2026-10-07T11:13:42Z","object_id":{"id":3045,"is_a":["text","documentation","developerguide"],"name":"developer_local_postgresql","title":{"_type":"trans","tr":{"en":"Prepare local PostgreSQL"}},"uri":"https:\/\/zotonic.com\/id\/3045"},"seq":1},{"created":"2026-10-07T11:13:42Z","object_id":{"id":3070,"is_a":["text","documentation","adminguide"],"name":"admin_database_connection","title":{"_type":"trans","tr":{"en":"Check or change a site database connection"}},"uri":"https:\/\/zotonic.com\/id\/3070"},"seq":2},{"created":"2026-10-07T11:13:42Z","object_id":{"id":2936,"is_a":["text","documentation","developerguide"],"name":"developer_database_shell","title":{"_type":"trans","tr":{"en":"Test the database connection"}},"uri":"https:\/\/zotonic.com\/id\/2936"},"seq":3}],"predicate":{"id":2774,"is_a":["meta","predicate"],"name":"hasreference","title":{"_type":"trans","tr":{"en":"Documentation reference"}},"uri":"https:\/\/zotonic.com\/id\/hasreference"}},"references":{"objects":[{"created":"2020-05-30T05:47:36Z","object_id":{"id":1599,"is_a":["text","documentation","cookbook"],"name":"doc_cookbook_shell_restoring_db","title":{"_type":"trans","tr":{"en":"Rehearse a complete site restore"}},"uri":"https:\/\/zotonic.com\/id\/1599"},"seq":1000000},{"created":"2020-05-30T05:47:36Z","object_id":{"id":1530,"is_a":["text","documentation","reference"],"name":"doc_reference_installation_requirements","title":{"_type":"trans","tr":{"en":"Installation requirements"}},"uri":"https:\/\/zotonic.com\/id\/1530"},"seq":1000000}],"predicate":{"id":332,"is_a":["meta","predicate"],"name":"references","title":{"_type":"trans","tr":{"en":"References"}},"uri":"https:\/\/zotonic.com\/id\/references"}},"refers":{"objects":[{"created":"2026-10-07T11:13:03Z","object_id":{"id":1411,"is_a":["text","documentation","developerguide"],"name":"doc_developerguide_docker","title":{"_type":"trans","tr":{"en":"Install with Docker or Podman"}},"uri":"https:\/\/zotonic.com\/id\/1411"},"seq":1000000},{"created":"2026-10-07T11:13:03Z","object_id":{"id":2913,"is_a":["text","documentation","developerguide"],"name":"developer_build_start","title":{"_type":"trans","tr":{"en":"Build and start Zotonic"}},"uri":"https:\/\/zotonic.com\/id\/2913"},"seq":1000000},{"created":"2026-10-07T11:13:03Z","object_id":{"id":3005,"is_a":["text","documentation","developerguide"],"name":"developer_cmd_addsite","title":{"_type":"trans","tr":{"en":"addsite: Create a site application from a skeleton"}},"uri":"https:\/\/zotonic.com\/id\/3005"},"seq":1000000}],"predicate":{"id":2409,"is_a":["meta","predicate"],"name":"refers","title":{"_type":"trans","tr":{"en":"Refers"}},"uri":"https:\/\/zotonic.com\/id\/refers"}},"subject":{"objects":[{"created":"2026-10-07T11:13:42Z","object_id":{"id":2553,"is_a":["categorization","keyword","keyword_information_type"],"name":"zotonic_topic_tutorial","title":"Tutorial","uri":"https:\/\/zotonic.com\/id\/2553"},"seq":1},{"created":"2026-10-07T11:13:42Z","object_id":{"id":2564,"is_a":["categorization","keyword","keyword_audience"],"name":"zotonic_topic_backend_developer","title":"Backend developer","uri":"https:\/\/zotonic.com\/id\/2564"},"seq":2},{"created":"2026-10-07T11:13:42Z","object_id":{"id":2671,"is_a":["categorization","keyword","keyword_technology"],"name":"zotonic_topic_postgresql","title":"PostgreSQL","uri":"https:\/\/zotonic.com\/id\/2671"},"seq":3},{"created":"2026-10-07T11:13:42Z","object_id":{"id":2631,"is_a":["categorization","keyword","keyword_architecture"],"name":"zotonic_topic_database","title":"Database","uri":"https:\/\/zotonic.com\/id\/2631"},"seq":4}],"predicate":{"id":308,"is_a":["meta","predicate"],"name":"subject","title":{"_type":"trans","tr":{"en":"Keyword"}},"uri":"http:\/\/purl.org\/dc\/elements\/1.1\/subject"}}},"id":1600,"is_a":["text","documentation","cookbook"],"links":[{"rel":"self","target":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/1600"},{"rel":"hub","target":"https:\/\/zotonic.com\/.zotonic\/websub"}],"medium":null,"medium_url":null,"name":"doc_cookbook_justenough_postgres","page_url":{"en":"https:\/\/zotonic.com\/cookbook\/1600\/prepare-local-postgresql","x-default":"https:\/\/zotonic.com\/cookbook\/1600\/prepare-local-postgresql"},"preview_url":null,"resource":{"body":{"_type":"trans","tr":{"en":"<p>Use this page for the native installation or a Nix development shell. The <a href=\"\/id\/1411\">container route<\/a> already configures PostgreSQL; skip this page for containers.<\/p>\n<h2>1. Open a database administrator session<\/h2>\n<p>On Ubuntu\/Debian with the PostgreSQL service running:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-sh\">sudo -u postgres psql\n<\/code><\/pre>\n<p>On macOS with a fresh Homebrew PostgreSQL installation:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-sh\">psql postgres\n<\/code><\/pre>\n<p>An existing installation may use a different administrator account. Use that account rather than resetting an existing database.<\/p>\n<h2>2. Create a local development role and database<\/h2>\n<p>At the <code>psql<\/code> prompt:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-sql\">CREATE ROLE zotonic LOGIN;\n\\password zotonic\nCREATE DATABASE zotonic OWNER zotonic ENCODING &#39;UTF8&#39; TEMPLATE template0;\n\\q\n<\/code><\/pre>\n<p>For this disposable local example, enter <code>zotonic<\/code> at both password prompts. This matches Zotonic&#39;s development defaults. Use it only on your local development machine. If the role or database already exists, inspect its owner and settings instead of recreating it or changing its password blindly.<\/p>\n<p>The <code>garden<\/code> site will use its own schema inside this database. The database owner can create that schema; the application role does not need superuser privileges.<\/p>\n<h2>3. Test the same connection Zotonic will use<\/h2>\n<pre class=\"notranslate\"><code class=\"notranslate language-sh\">psql -h localhost -U zotonic -d zotonic -W -c &#39;SELECT current_user, current_database();&#39;\npsql -h localhost -U zotonic -d postgres -W -c &#39;SELECT current_database();&#39;\n<\/code><\/pre>\n<p>Enter the development password. Expect <code>zotonic<\/code> for both values in the first query and <code>postgres<\/code> in the second. <code>addsite<\/code> also connects to the <code>postgres<\/code> maintenance database to check that the site database exists. Do not continue to <code>addsite<\/code> until this succeeds.<\/p>\n<p>If the server refuses the connection, check that PostgreSQL is running on localhost port 5432. If authentication fails, check the password and the first matching <code>pg_hba.conf<\/code> rule. From the administrator&#39;s <code>psql<\/code> session, <code>SHOW hba_file;<\/code> locates that file. A local password-based configuration can use:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-text\">host    zotonic,postgres    zotonic    127.0.0.1\/32    scram-sha-256\nhost    zotonic,postgres    zotonic    ::1\/128         scram-sha-256\n<\/code><\/pre>\n<p>Place specific rules before a broader conflicting rule, then reload PostgreSQL with <code>SELECT pg_reload_conf();<\/code> in the administrator session. <a href=\"https:\/\/www.postgresql.org\/docs\/16\/auth-pg-hba-conf.html\">PostgreSQL&#39;s authentication documentation<\/a> explains that only the first matching rule applies.<\/p>\n<h2>Optional: use a local Unix socket<\/h2>\n<p>If Zotonic and PostgreSQL run on the same host, you can use a Unix socket instead of TCP. In Zotonic&#39;s database configuration, set <code>{dbhost, socket}<\/code> for <code>\/run\/postgresql<\/code>, or <code>{dbhost, &quot;\/var\/run\/postgresql&quot;}<\/code> for a different absolute socket directory. The configured <code>dbport<\/code> selects the socket filename <code>.s.PGSQL.&lt;port&gt;<\/code>; it is normally 5432. Use the actual directory reported by <code>SHOW unix_socket_directories;<\/code>.<\/p>\n<p>For example, in the site&#39;s configuration term list:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-erlang\">{dbhost, socket},\n{dbport, 5432}\n<\/code><\/pre>\n<p>Test the same endpoint and role:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-sh\">psql -h \/run\/postgresql -p 5432 -U zotonic -d zotonic -W\n<\/code><\/pre>\n<p>Socket connections match <code>local<\/code> rules in <code>pg_hba.conf<\/code>. For password authentication, a specific rule is <code>local zotonic,postgres zotonic scram-sha-256<\/code>. Peer authentication instead checks the operating-system identity: test as the service user and configure a deliberate user mapping when the names differ. Socket mode does not silently fall back to TCP. The service must be able to access the socket directory; a container needs an explicitly shared socket path.<\/p>\n<p>When creating a site, use <code>bin\/zotonic addsite -h socket garden<\/code> (or the absolute directory after <code>-h<\/code>) together with any other required database options.<\/p>\n<h2>4. Continue the installation<\/h2>\n<p><a href=\"\/id\/2913\">Build and start Zotonic<\/a>, then create <code>garden<\/code>. For a different database host, role, or password, configure those values before creating the site; see <a href=\"\/id\/3005\">the addsite options<\/a>. Container connections use host <code>postgres<\/code>, not <code>localhost<\/code>.<\/p>\n<h2>Check or change a site database connection<\/h2>\n<p><strong>Access needed:<\/strong> Database and server configuration access.<\/p>\n<ol><li>Identify the site&#39;s effective database host, port, database name, role, and schema. Do not print the password into a shared report.<\/li><li>Test connectivity from the same host or container that runs Zotonic. A successful connection from your laptop may follow a different route.<\/li><li>Check authentication and the role&#39;s access to the intended database and schema.<\/li><li>Make a required connection change in acceptance first, at the owning configuration layer.<\/li><li>Restart or reload according to the deployment procedure and check startup logs.<\/li><li>Verify an existing page and a small write using the intended site account. Confirm that you did not connect to an empty or wrong environment&#39;s database.<\/li><\/ol>\n<p>A schema separates site tables within a database; it is not a substitute for environment isolation. Do not grant superuser rights to bypass a permissions error. For a fresh local development database, use the developer setup task instead of adapting production credentials.<\/p>\n<h2>Local socket connections<\/h2>\n<p>For PostgreSQL on the same host, set <code>dbhost<\/code> to <code>socket<\/code> (atom, string, or binary) to use <code>\/run\/postgresql<\/code>, or set it to an absolute socket directory. <code>dbport<\/code> selects <code>.s.PGSQL.&lt;port&gt;<\/code>, normally <code>.s.PGSQL.5432<\/code>. This mode does not fall back to TCP.<\/p>\n<p>Check <code>SHOW unix_socket_directories;<\/code> in PostgreSQL and test with <code>psql -h \/run\/postgresql -p 5432 -U ROLE -d DATABASE<\/code> as the Zotonic service user. Socket connections use <code>local<\/code> rules in <code>pg_hba.conf<\/code>; TCP connections use <code>host<\/code> rules. Match the intended password or peer-authentication policy. Keep the socket directory writable only by trusted users. For containers, verify the mount and permissions inside the container.<\/p>\n<h2>Test the database connection<\/h2>\n<p>Run <code>bin\/zotonic connectdb<\/code> to test a connection using the global Zotonic database configuration. It does not open PostgreSQL’s interactive client and has no site selector in this checkout.<\/p>\n<p>The command prints connection options, including the password, before testing. Keep that output private. A site can override global database settings, so success does not prove that its own database and schema are available.<\/p>\n<p>For a site-specific investigation, inspect its configuration and use a database client deliberately, or query application data through Zotonic models with the correct context. Prefer models for normal mutations so notifications and cache invalidation remain coordinated.<\/p>"}},"category_id":{"id":318,"is_a":["meta","category"],"name":"cookbook","title":{"_type":"trans","tr":{"en":"Cookbook"}},"uri":"https:\/\/test.zotonic.com\/id\/318"},"content_group_id":{"id":339,"is_a":["meta","content_group"],"name":"default_content_group","title":{"_type":"trans","tr":{"en":"Default Content Group"}},"uri":"https:\/\/zotonic.com\/id\/default_content_group"},"created":"2020-05-30T05:47:27Z","creator_id":{"id":336,"is_a":["person","robot"],"name":"gitbot","title":"Git","uri":"https:\/\/zotonic.com\/id\/336"},"doc_editorial_bundle":true,"doc_editorial_edges":{"hasreference":[2936,3045,3070],"subject":[2553,2564,2631,2671]},"github_url":"https:\/\/github.com\/zotonic\/zotonic\/tree\/master\/doc\/cookbook\/justenough-postgres.rst","is_authoritative":true,"is_dependent":false,"is_featured":false,"is_protected":false,"is_published":true,"is_unfindable":false,"language":["en"],"modified":"2026-10-07T11:13:52Z","modifier_id":{"id":1,"is_a":["person"],"name":"administrator","title":"Site Administrator","uri":"https:\/\/zotonic.com\/id\/1"},"name":"doc_cookbook_justenough_postgres","pivot_geocode":null,"pivot_location_lat":null,"pivot_location_lng":null,"privacy":0,"publication_end":"9999-06-01T00:00:00Z","publication_start":"2022-02-15T10:01:29Z","slug":"prepare-local-postgresql","summary":{"_type":"trans","tr":{"en":"Create and check the database used by a native development installation."}},"title":{"_type":"trans","tr":{"en":"Prepare local PostgreSQL"}},"title_slug":{"_type":"trans","tr":{"en":"prepare-local-postgresql"}},"tz":"UTC","uri":null,"version":38,"visible_for":0},"uri":"https:\/\/zotonic.com\/id\/1600","uri_template":"https:\/\/zotonic.com\/id\/:id","websub":{"hub":"https:\/\/zotonic.com\/.zotonic\/websub","topic":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/1600"}},"status":"ok"}