Hi guys,
I’m trying to reinstall my grampsweb docker stack with Postgres DB, and allow it to use the shared trees addon too.
I’ve followed the documentation for it, which was quite confusing due to the varying name schemes of the environment variables.
So far, after wiping the whole directory for gramps, I get the following with the new postgres container:
CREATE DATABASE
GRANT
You are now connected to database "gramps" as user "postgres".
GRANT
CREATE EXTENSION
/usr/local/bin/docker-entrypoint.sh: sourcing /docker-entrypoint-initdb.d/20-grampswebuser.sh
CREATE ROLE
CREATE DATABASE
GRANT
You are now connected to database "grampswebuser" as user "postgres".
GRANT
CREATE EXTENSION
waiting for server to shut down...2025-04-13 16:07:59.579 UTC [49] LOG: received fast shutdown request
.2025-04-13 16:07:59.593 UTC [49] LOG: aborting any active transactions
2025-04-13 16:07:59.594 UTC [49] LOG: background worker "logical replication launcher" (PID 55) exited with exit code 1
2025-04-13 16:07:59.595 UTC [50] LOG: shutting down
2025-04-13 16:07:59.606 UTC [50] LOG: checkpoint starting: shutdown immediate
...2025-04-13 16:08:03.545 UTC [50] LOG: checkpoint complete: wrote 1927 buffers (11.8%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.014 s, sync=3.847 s, total=3.951 s; sync files=604, longest=0.139 s, average=0.007 s; distance=9441 kB, estimate=9441 kB
2025-04-13 16:08:03.560 UTC [49] LOG: database system is shut down
done
server stopped
PostgreSQL init process complete; ready for start up.
2025-04-13 16:08:03.657 UTC [1] LOG: starting PostgreSQL 15.8 (Debian 15.8-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
2025-04-13 16:08:03.658 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
2025-04-13 16:08:03.658 UTC [1] LOG: listening on IPv6 address "::", port 5432
2025-04-13 16:08:03.683 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2025-04-13 16:08:03.705 UTC [69] LOG: database system was shut down at 2025-04-13 16:08:03 UTC
2025-04-13 16:08:03.750 UTC [1] LOG: database system is ready to accept connections
2025-04-13 16:08:06.357 UTC [74] ERROR: duplicate key value violates unique constraint "pg_type_typname_nsp_index"
2025-04-13 16:08:06.357 UTC [74] DETAIL: Key (typname, typnamespace)=(alembic_version, 2200) already exists.
2025-04-13 16:08:06.357 UTC [74] STATEMENT:
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL,
CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
)
As for the grampsweb container, I get the following:
sqlalchemy.exc.IntegrityError: (psycopg2.errors.UniqueViolation) duplicate key value violates unique constraint "pg_type_typname_nsp_index"
DETAIL: Key (typname, typnamespace)=(alembic_version, 2200) already exists.
[SQL:
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL,
CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
)
]
(Background on this error at: https://sqlalche.me/e/20/gkpj)
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "/app/src/gramps_webapi/__main__.py", line 317, in <module>
cli(
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1161, in __call__
return self.main(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1082, in main
rv = self.invoke(ctx)
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1697, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1697, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 1443, in invoke
return ctx.invoke(self.callback, **ctx.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/core.py", line 788, in invoke
return __callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/click/decorators.py", line 33, in new_func
return f(get_current_context(), *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/src/gramps_webapi/__main__.py", line 191, in migrate_db
subprocess.run(cmd, env=env, check=True)
File "/usr/lib/python3.11/subprocess.py", line 571, in run
raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['/usr/bin/python3', '-m', 'alembic', 'upgrade', 'head']' returned non-zero exit status 1.
(__main__.py:7): Gtk-CRITICAL **: 16:08:09.427: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
[2025-04-13 16:08:10 +0000] [11] [INFO] Starting gunicorn 23.0.0
[2025-04-13 16:08:10 +0000] [11] [INFO] Listening at: http://0.0.0.0:5000 (11)
[2025-04-13 16:08:10 +0000] [11] [INFO] Using worker: sync
[2025-04-13 16:08:10 +0000] [12] [INFO] Booting worker with pid: 12
[2025-04-13 16:08:10 +0000] [13] [INFO] Booting worker with pid: 13
[2025-04-13 16:08:10 +0000] [14] [INFO] Booting worker with pid: 14
[2025-04-13 16:08:10 +0000] [15] [INFO] Booting worker with pid: 15
[2025-04-13 16:08:10 +0000] [18] [INFO] Booting worker with pid: 18
[2025-04-13 16:08:10 +0000] [19] [INFO] Booting worker with pid: 19
[2025-04-13 16:08:10 +0000] [22] [INFO] Booting worker with pid: 22
[2025-04-13 16:08:10 +0000] [23] [INFO] Booting worker with pid: 23
(gunicorn:12): Gtk-CRITICAL **: 16:08:11.867: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(gunicorn:13): Gtk-CRITICAL **: 16:08:11.968: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(gunicorn:15): Gtk-CRITICAL **: 16:08:12.087: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(gunicorn:19): Gtk-CRITICAL **: 16:08:12.200: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(gunicorn:22): Gtk-CRITICAL **: 16:08:12.224: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(gunicorn:18): Gtk-CRITICAL **: 16:08:12.429: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(gunicorn:14): Gtk-CRITICAL **: 16:08:12.473: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
(gunicorn:23): Gtk-CRITICAL **: 16:08:12.514: gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
My docker compose (without the env variables) is as follows:
services:
grampsweb: &grampsweb
image: ghcr.io/gramps-project/grampsweb:latest
restart: always
ports:
- "5314:5000" # host:docker
environment:
GRAMPSWEB_TREE: ${GRAMPSWEB_TREE}
GRAMPSWEB_CELERY_CONFIG__broker_url: ${GRAMPSWEB_CELERY_CONFIG__broker_url}
GRAMPSWEB_CELERY_CONFIG__result_backend: ${GRAMPSWEB_CELERY_CONFIG__result_backend}
GRAMPSWEB_RATELIMIT_STORAGE_URI: ${GRAMPSWEB_RATELIMIT_STORAGE_URI}
GRAMPSWEB_SECRET_KEY: ${GRAMPSWEB_SECRET_KEY}
GRAMPSWEB_BASE_URL: ${GRAMPSWEB_BASE_URL}
GRAMPSWEB_MEDIA_PREFIX_TREE: ${GRAMPSWEB_MEDIA_PREFIX_TREE}
#Email
GRAMPSWEB_EMAIL_HOST: ${GRAMPSWEB_EMAIL_HOST}
GRAMPSWEB_EMAIL_PORT: ${GRAMPSWEB_EMAIL_PORT}
GRAMPSWEB_EMAIL_USE_TLS: ${GRAMPSWEB_EMAIL_USE_TLS}
GRAMPSWEB_EMAIL_HOST_USER: ${GRAMPSWEB_EMAIL_HOST_USER}
GRAMPSWEB_EMAIL_HOST_PASSWORD: ${GRAMPSWEB_EMAIL_HOST_PASSWORD}
GRAMPSWEB_DEFAULT_FROM_EMAIL: ${GRAMPSWEB_DEFAULT_FROM_EMAIL}
# the PostgreSQL addon assumes the tree name to be
# equal to the database name and here the default
# database name of the PostgreSQL image is used
# The credentials must agree with the ones used for
# the PostgreSQL container
GRAMPSWEB_POSTGRES_USER: ${GRAMPSWEB_POSTGRES_USER}
GRAMPSWEB_POSTGRES_PASSWORD: ${GRAMPSWEB_POSTGRES_PASSWORD_GRAMPS}
GRAMPSWEB_USER_DB_URI: ${GRAMPSWEB_USER_DB_URI}
GRAMPSWEB_SEARCH_INDEX_DB_URI: ${GRAMPSWEB_SEARCH_INDEX_DB_URI}
GRAMPSWEB_NEW_DB_BACKEND: ${GRAMPSWEB_NEW_DB_BACKEND}
#A.I.
GRAMPSWEB_LLM_BASE_URL: ${GRAMPSWEB_LLM_BASE_URL}
GRAMPSWEB_LLM_MODEL: ${GRAMPSWEB_LLM_MODEL}
GRAMPSWEB_VECTOR_EMBEDDING_MODEL: ${GRAMPSWEB_VECTOR_EMBEDDING_MODEL}
GRAMPSWEB_LLM_MAX_CONTEXT_LENGTH: ${GRAMPSWEB_LLM_MAX_CONTEXT_LENGTH}
GRAMPSWEB_OPENAI_API_KEY: ${GRAMPSWEB_OPENAI_API_KEY}
depends_on:
- grampsweb_redis
volumes:
- /mnt/tank/appdata/gramps/users:/app/users # persist user database
- /mnt/tank/appdata/gramps/index:/app/indexdir # persist search index
- /mnt/tank/appdata/gramps/thumbnail_cache:/app/thumbnail_cache # persist thumbnails
- /mnt/tank/appdata/gramps/cache:/app/cache # persist export and report caches
- /mnt/tank/appdata/gramps/secret:/app/secret # persist flask secret
- /mnt/tank/appdata/gramps/db:/root/.gramps/grampsdb # persist Gramps database
- /mnt/tank/appdata/gramps/media:/app/media # persist media files
- /mnt/tank/appdata/gramps/tmp:/tmp # temporary files
grampsweb_celery:
<<: *grampsweb # YAML merge key copying the entire grampsweb service config
ports: []
container_name: grampsweb_celery
depends_on:
- grampsweb_redis
command: celery -A gramps_webapi.celery worker --loglevel=INFO
grampsweb_redis:
image: redis:7.2.4-alpine
container_name: grampsweb_redis
restart: always
postgres_gramps:
image: ghcr.io/davidmstraub/gramps-postgres:latest
restart: unless-stopped
environment:
POSTGRES_PASSWORD: ${GRAMPSWEB_POSTGRES_PASSWORD}
POSTGRES_PASSWORD_GRAMPS: ${GRAMPSWEB_POSTGRES_PASSWORD_GRAMPS}
POSTGRES_PASSWORD_GRAMPS_USER: ${GRAMPSWEB_POSTGRES_PASSWORD_GRAMPS_USER}
volumes:
- /mnt/tank/appdata/gramps/db/postgres:/var/lib/postgresql/data
And here are the env variables, with the passwords and logins hidden, but with numbers to show whether they are different:
GRAMPSWEB_TREE=* # will create a new tree if not exists
GRAMPSWEB_CELERY_CONFIG__broker_url="redis://grampsweb_redis:6379/0"
GRAMPSWEB_CELERY_CONFIG__result_backend="redis://grampsweb_redis:6379/0"
GRAMPSWEB_RATELIMIT_STORAGE_URI=redis://grampsweb_redis:6379/1
GRAMPSWEB_SECRET_KEY=#hiddenpassword4
GRAMPSWEB_BASE_URL=https://grampsweb.domain.ltd
GRAMPSWEB_EMAIL_HOST=smtp.gmail.com
GRAMPSWEB_EMAIL_PORT=587
GRAMPSWEB_EMAIL_USE_TLS=True
GRAMPSWEB_EMAIL_HOST_USER=myemail@domain.ltd
GRAMPSWEB_EMAIL_HOST_PASSWORD=#hiddensmtppassword
GRAMPSWEB_DEFAULT_FROM_EMAIL=myemail@domain.ltd
GRAMPSWEB_POSTGRES_USER=gramps
GRAMPSWEB_POSTGRES_PASSWORD=#hiddenpassword1
GRAMPSWEB_POSTGRES_PASSWORD_GRAMPS=#hiddenpassword2
GRAMPSWEB_POSTGRES_PASSWORD_GRAMPS_USER=#hiddenpassword3
GRAMPSWEB_USER_DB_URI=postgresql://grampswebuser:$GRAMPSWEB_POSTGRES_PASSWORD_GRAMPS_USER@postgres_gramps:5432/grampswebuser
GRAMPSWEB_SEARCH_INDEX_DB_URI=postgresql://gramps:$GRAMPSWEB_POSTGRES_PASSWORD_GRAMPS@postgres_gramps:5432/gramps
GRAMPSWEB_NEW_DB_BACKEND=sharedpostgresql
GRAMPSWEB_MEDIA_PREFIX_TREE=True
GRAMPSWEB_LLM_BASE_URL=
GRAMPSWEB_LLM_MODEL=gpt-4o-mini
GRAMPSWEB_VECTOR_EMBEDDING_MODEL=
GRAMPSWEB_LLM_MAX_CONTEXT_LENGTH=
GRAMPSWEB_OPENAI_API_KEY=#hidden
The documentation is quite confusing, especially due to the fact that it says to use the “GRAMPSWEB_” prefix for every variable, but then, I don’t know if it’s exactly every variable. For the postgres container, for example.
I can get to the web ui with this setup, but it’s unable to create the user. (gives a cross in a red circle).
Any help is appreciated.