Walwarden
GuidesConnect a database

Connect Neon

Register a Neon Postgres database for scheduled backups to storage you own.

Neon is a shipping source provider. The shipping onboarding path is manual connection-string entry.

OAuth availability

Neon OAuth onboarding does not ship today; use the manual DSN path.

  • Neon OAuth client registration is available only to an active commercial partner.
  • The planned partner flow uses state, S256 PKCE, read-only project and organization scopes, and offline access for refresh.

Manual setup remains available independently of provider partner approval or OAuth configuration.

Official provider references:

Prerequisites

  • A configured, preflight-verified backup destination. The destination is attached after database creation from the database detail page.
  • A dedicated database role with CONNECT on the database, USAGE on each included schema, and SELECT on the tables and sequences to back up. Superuser is not required.
  • A Neon project, branch, database, and role you want to protect.

Create a scoped read login

Run the plan through Neon SQL Editor or psql. Do not create the role through the Neon Console, CLI, or API because those paths add neon_superuser membership.

The plan below is idempotent for the same generated role. Replace the password sentinel locally with a secret made from 32 browser-CSPRNG bytes and encoded as exactly 43 unpadded base64url characters. Repeat the schema and default-privilege clauses for every selected application schema and every role that creates future objects. Do not send password-bearing SQL to Walwarden or store it in browser storage.

BEGIN;

DO $walwarden$
DECLARE
  role_oid oid;
BEGIN
  SELECT oid INTO role_oid
  FROM pg_roles
  WHERE rolname = 'walwarden_backup_a1b2c3d4';

  IF role_oid IS NULL THEN
    CREATE ROLE "walwarden_backup_a1b2c3d4"
      WITH LOGIN NOINHERIT NOSUPERUSER NOCREATEDB NOCREATEROLE
           NOREPLICATION NOBYPASSRLS CONNECTION LIMIT 4
           PASSWORD '__WALWARDEN_PASSWORD_BASE64URL_43__';
    COMMENT ON ROLE "walwarden_backup_a1b2c3d4" IS 'walwarden-source-role-plan:v1:0123456789abcdef0123456789abcdef';
  ELSIF EXISTS (
    SELECT 1
    FROM pg_roles r
    WHERE r.oid = role_oid
      AND (
        NOT r.rolcanlogin OR r.rolsuper OR r.rolcreatedb OR r.rolcreaterole
        OR r.rolreplication OR r.rolbypassrls OR r.rolinherit
        OR r.rolconnlimit < 1 OR r.rolconnlimit > 4
      )
  ) OR EXISTS (
    SELECT 1
    FROM pg_auth_members
    WHERE member = role_oid OR roleid = role_oid
  ) OR shobj_description(role_oid, 'pg_authid') IS DISTINCT FROM 'walwarden-source-role-plan:v1:0123456789abcdef0123456789abcdef' THEN
    RAISE EXCEPTION 'existing Walwarden role has an incompatible security shape';
  END IF;
END
$walwarden$;

GRANT CONNECT ON DATABASE "your_database" TO "walwarden_backup_a1b2c3d4";

GRANT USAGE ON SCHEMA "public" TO "walwarden_backup_a1b2c3d4";
GRANT SELECT ON ALL TABLES IN SCHEMA "public"
  TO "walwarden_backup_a1b2c3d4";
GRANT SELECT ON ALL SEQUENCES IN SCHEMA "public"
  TO "walwarden_backup_a1b2c3d4";

ALTER DEFAULT PRIVILEGES FOR ROLE "your_migration_role"
  IN SCHEMA "public"
  GRANT SELECT ON TABLES TO "walwarden_backup_a1b2c3d4";
ALTER DEFAULT PRIVILEGES FOR ROLE "your_migration_role"
  IN SCHEMA "public"
  GRANT SELECT ON SEQUENCES TO "walwarden_backup_a1b2c3d4";

COMMIT;

Dashboard SQL editors retain statements in provider SQL history. Use the psql interactive-password flow when SQL history must not contain the one-time password.

This SQL requests a scoped read login, but SQL generation alone does not prove its effective privileges. Before use, audit direct, inherited, owner-derived, and PUBLIC capabilities. Persistent database/schema CREATE, table or sequence writes, role administration, replication, RLS bypass, ownership, memberships, grant options, or callable non-system SECURITY DEFINER routines are blocking. PostgreSQL may still grant session-local TEMPORARY through PUBLIC; disclose that residual explicitly. A complete dump of an RLS-protected table requires elevated access, so Walwarden must fail closed rather than recommend BYPASSRLS.

Future grants are creator-specific: replace your_migration_role with every role that creates objects in the schema. Re-run privilege validation after changing schemas or migration roles.

Disable and revoke the login

Use the paired plan during rotation or revoke:

BEGIN;

ALTER ROLE "walwarden_backup_a1b2c3d4" NOLOGIN;

ALTER DEFAULT PRIVILEGES FOR ROLE "your_migration_role"
  IN SCHEMA "public"
  REVOKE SELECT ON TABLES FROM "walwarden_backup_a1b2c3d4";
ALTER DEFAULT PRIVILEGES FOR ROLE "your_migration_role"
  IN SCHEMA "public"
  REVOKE SELECT ON SEQUENCES FROM "walwarden_backup_a1b2c3d4";

REVOKE SELECT ON ALL SEQUENCES IN SCHEMA "public" FROM "walwarden_backup_a1b2c3d4";
REVOKE SELECT ON ALL TABLES IN SCHEMA "public" FROM "walwarden_backup_a1b2c3d4";
REVOKE USAGE ON SCHEMA "public" FROM "walwarden_backup_a1b2c3d4";

REVOKE CONNECT ON DATABASE "your_database" FROM "walwarden_backup_a1b2c3d4";

COMMIT;

Drop the role only as a separately confirmed final step after analysis proves that it owns nothing and has no cross-database dependencies.

The create form does not prove those schema and table grants. It rejects invalid or incompatible connection shapes; depending on deployment probe mode it may also check connectivity, authentication, TLS, and transaction-pooler compatibility. A real backup is the first end-to-end permission check.

Step 1: Get a safe connection string

Open the Neon project, select the branch, database, and role, then choose the unpooled connection details.

Use the direct, unpooled endpoint; a hostname containing -pooler is not the backup endpoint.

Use the exact Neon branch direct, non--pooler endpoint for pg_dump.

  • Choose Pooled connection off in the Neon connection details and use the direct endpoint.
  • Keep sslmode=require and any provider-required channel_binding parameter in the URI.
  • Do not use a -pooler endpoint for pg_dump backup work.

Manual onboarding requires the selected database role password in the submitted DSN.

postgresql://walwarden_backup:<password>@<endpoint>.neon.tech/<database>?sslmode=require

Step 2: Add the protected database

  1. In the Walwarden dashboard, open Protected databases → Add database.
  2. Choose Neon, enter a display name such as neon-main, and paste the connection string.
  3. Choose the optional backup schedule, retention, and data-residency settings, then select Connect database.
  4. From the new database detail page, attach a configured, preflight-verified destination. Destination selection is not part of the database-create form.

Source credential custody

The DSN stays in page memory while you edit it and is never written to localStorage or sessionStorage.

The submitted source DSN is stored server-side by Walwarden so the backup worker can connect. The current shipping create path is not yet an envelope-encryption claim.

Approved envelope model — rollout not yet claimed as shipping

After the approved envelope rollout is production-proven, the web control plane will be seal-only, the worker will be the only decrypt principal, and each credential rotation will create a fresh data-encryption key wrapped by the configured KMS key generation.

Verify it worked

Attach a verified destination and trigger a backup. A completed backup with artifact and integrity evidence confirms that bytes landed in the destination; backup completion alone does not prove recoverability. Use an operator-run restore drill for recovery evidence.

Scheduled backups · Ad-hoc backups · Run a restore drill