diff --git a/.gitignore b/.gitignore index 116ea01a..a2473f35 100644 --- a/.gitignore +++ b/.gitignore @@ -129,6 +129,7 @@ docker-compose.override.yml # test directory is used as media directory, we don't want to commit what a user downloads. /test +# Legacy local Postgres data directory from pre-SQLite docker-compose (safe to delete). pg_data # Directories used to build images diff --git a/app/src/components/Headline.js b/app/src/components/Headline.js index 5cf1b391..e70733d3 100644 --- a/app/src/components/Headline.js +++ b/app/src/components/Headline.js @@ -14,7 +14,7 @@ export const HeadlineText = ({headline, openTag = '', closeTag = ''}) => headline = headline.replaceAll('', openTag); headline = headline.replaceAll('', closeTag); headline = headline.replaceAll('\n', '
'); - // Postgres inserts ... tags which we will use. + // FTS headlines use ... tags which we will restyle. return } } diff --git a/controller/lib/docker_services.py b/controller/lib/docker_services.py index 83afb516..82459363 100644 --- a/controller/lib/docker_services.py +++ b/controller/lib/docker_services.py @@ -27,7 +27,7 @@ except ImportError: CONTAINER_PREFIX = os.environ.get("COMPOSE_PROJECT_NAME", "wrolpi") # Containers that should not have a "View" button (non-HTTP services) -NON_VIEWABLE_CONTAINERS = {"db", "postgres", "postgresql", "redis", "memcached", "samba"} +NON_VIEWABLE_CONTAINERS = {"redis", "memcached", "samba"} # Containers that should use HTTPS HTTPS_CONTAINERS = {"web"} diff --git a/controller/test/test_docker_services.py b/controller/test/test_docker_services.py index 2a3e3cf6..1a417c76 100644 --- a/controller/test/test_docker_services.py +++ b/controller/test/test_docker_services.py @@ -127,12 +127,12 @@ class TestGetAllContainersStatus: assert len(result) == 1 assert result[0]["name"] == "api" - def test_db_container_not_viewable(self): - """Database container should not be viewable (port 5432 is not HTTP).""" + def test_samba_container_not_viewable(self): + """Samba container should not be viewable (SMB is not HTTP).""" mock_container = mock.Mock() - mock_container.name = f"{CONTAINER_PREFIX}-db-1" + mock_container.name = f"{CONTAINER_PREFIX}-samba-1" mock_container.status = "running" - mock_container.attrs = {"NetworkSettings": {"Ports": {"5432/tcp": [{"HostPort": "5432"}]}}} + mock_container.attrs = {"NetworkSettings": {"Ports": {"445/tcp": [{"HostPort": "445"}]}}} mock_client = mock.Mock() mock_client.containers.list.return_value = [mock_container] @@ -141,7 +141,7 @@ class TestGetAllContainersStatus: with mock.patch("controller.lib.docker_services._get_client", return_value=mock_client): result = get_all_containers_status() assert len(result) == 1 - assert result[0]["name"] == "db" + assert result[0]["name"] == "samba" assert result[0]["viewable"] is False def test_api_container_is_viewable(self): diff --git a/modules/archive/test/test_api.py b/modules/archive/test/test_api.py index 684c6656..5e90abc9 100644 --- a/modules/archive/test/test_api.py +++ b/modules/archive/test/test_api.py @@ -136,7 +136,7 @@ async def test_archives_search_headline(test_session, archive_directory, archive request, response = await async_client.post('/api/archive/search', content=json.dumps(content)) assert response.status_code == HTTPStatus.OK - # Postgresql uses ... to highlight matching words. + # FTS headlines use ... to highlight matching words. assert response.json['file_groups'][0]['d_headline'] == 'foo baz qux qux' assert response.json['file_groups'][1]['d_headline'] == 'foo bar qux' diff --git a/modules/videos/models.py b/modules/videos/models.py index 573a43a9..3b013937 100644 --- a/modules/videos/models.py +++ b/modules/videos/models.py @@ -29,7 +29,7 @@ class Video(ModelHelper, Base): Index('video_channel_id_idx', 'channel_id'), Index('video_source_id_idx', 'source_id'), Index('video_view_count_idx', 'view_count'), - # Do not reuse ids of deleted Videos (like Postgres sequences). + # Do not reuse ids of deleted Videos (AUTOINCREMENT keeps a sequence table). {'sqlite_autoincrement': True}, ) id = Column(Integer, primary_key=True) diff --git a/pi-gen/README.md b/pi-gen/README.md index b7b9407a..a2eda28a 100644 --- a/pi-gen/README.md +++ b/pi-gen/README.md @@ -6,16 +6,8 @@ See https://github.com/RPI-Distro/pi-gen ## Generate 64bit Raspberry Pi WROLPi image -1. Convert a map PBF file to your initial map DB dump: - - docker run --rm -v /home/user/district-of-columbia-230111.osm.pbf:/data/region.osm.pbf lrnselfreliance/osm-map-dumper > pi-gen/stage2/04-wrolpi/files/map-db-gis.dump - - The output is already compressed (PostgreSQL custom format with `--compress 9`). - - Verify the dump format is correct: - - file pi-gen/stage2/04-wrolpi/files/map-db-gis.dump - # Should show: "PostgreSQL custom database dump" +1. (Optional) Place any default map assets under `pi-gen/stage2/04-wrolpi/files/` if the image + should ship with preloaded map data. Maps use PMTiles files served from `/media/wrolpi/map/`. 2. Run the build (or, with a specific git branch) diff --git a/repair.sh b/repair.sh index 567deb1e..f3f82292 100755 --- a/repair.sh +++ b/repair.sh @@ -35,10 +35,6 @@ find /opt/wrolpi-help/venv -name "*.pyc" -delete 2>/dev/null || : # Create the WROLPi user grep wrolpi: /etc/passwd || useradd -md /home/wrolpi wrolpi -s "$(command -v bash)" -[ -f /home/wrolpi/.pgpass ] || cat >/home/wrolpi/.pgpass <<'EOF' -127.0.0.1:5432:wrolpi:wrolpi:wrolpi -EOF -chmod 0600 /home/wrolpi/.pgpass # Reset any inadvertent changes to the WROLPi repo. Restore ownership in case this repair script fails. git config --global --add safe.directory /opt/wrolpi @@ -167,15 +163,8 @@ fi # Change owner of the media directory, ignore any errors because the drive may be fat/exfat/etc. chown wrolpi:wrolpi /media/wrolpi 2>/dev/null || echo "Ignoring failure to change media directory permissions." -# Ensure the config directory is owned by wrolpi so the API can write config files. +# Ensure the config directory is owned by wrolpi so the API can write config files and the SQLite DB. [ -d /media/wrolpi/config ] && chown -R wrolpi:wrolpi /media/wrolpi/config 2>/dev/null || : -# On Portable (live-boot) systems the Postgres cluster lives under config/postgresql, -# bind-mounted over /var/lib/postgresql — so the config chown above just swept it. Restore -# ownership only when that bind is active; on installed systems Postgres lives on the root -# filesystem and any config/postgresql directory is inert (dead weight or a user's backup). -if mountpoint -q /var/lib/postgresql 2>/dev/null && id postgres >/dev/null 2>&1; then - chown -R postgres:postgres /var/lib/postgresql /etc/postgresql 2>/dev/null || : -fi # Remove immutable flag from blob files before chown (may not exist or may not be set). chattr -i /opt/wrolpi-blobs/* 2>/dev/null || : diff --git a/scripts/install_protomaps.sh b/scripts/install_protomaps.sh index 5ec22c83..f1834505 100755 --- a/scripts/install_protomaps.sh +++ b/scripts/install_protomaps.sh @@ -62,10 +62,8 @@ rm -f /etc/apache2/conf-available/mod_tile.conf rm -f /etc/apache2/sites-available/000-default.conf rm -rf /etc/systemd/system/postgresql@15-map.service.d rm -f /var/www/html/leaflet.js /var/www/html/leaflet.css -# Remove old .pgpass entry for the map database. -if [ -f /home/wrolpi/.pgpass ]; then - sed -i '/5433/d' /home/wrolpi/.pgpass -fi +# Remove legacy Postgres client credentials (no longer used). +rm -f /home/wrolpi/.pgpass # --- Step 5: Update wrolpi.target to remove old services --- diff --git a/scripts/upgrade.sh b/scripts/upgrade.sh index 44278411..8fc5085d 100755 --- a/scripts/upgrade.sh +++ b/scripts/upgrade.sh @@ -102,14 +102,17 @@ find /opt/wrolpi/venv -name "*.pyc" -delete 2>/dev/null || : echo "WARNING: db upgrade failed (media directory unavailable?); the API will retry at startup." # WROLPi now uses SQLite (inside the media directory); stop and disable PostgreSQL to free -# system resources. The old Postgres data is NOT deleted -- to get it back: -# sudo systemctl enable --now postgresql +# system resources on upgrades from older installs. The old Postgres data is NOT deleted -- +# to get it back temporarily: sudo systemctl enable --now postgresql +# To reclaim disk later: sudo apt-get remove --purge postgresql* if id postgres >/dev/null 2>&1; then echo "Disabling PostgreSQL; WROLPi now uses SQLite. Your old Postgres data is untouched." # Stop the umbrella and any per-cluster instances (postgresql@15-main, etc.). systemctl stop 'postgresql*' 2>/dev/null || : systemctl disable postgresql 2>/dev/null || : fi +# Remove legacy Postgres client credentials (no longer used). +rm -f /home/wrolpi/.pgpass # Upgrade WROLPi Help. /opt/wrolpi/scripts/install_help_service.sh || echo "Help install failed." diff --git a/wrolpi/collections/models.py b/wrolpi/collections/models.py index 87ec1701..9914762e 100644 --- a/wrolpi/collections/models.py +++ b/wrolpi/collections/models.py @@ -1195,7 +1195,7 @@ class CollectionItem(ModelHelper, Base): Index('idx_collection_item_file_group_id', 'file_group_id'), Index('idx_collection_item_position', 'position'), # A FileGroup/Zim-article/URL appears at most once per collection. NULLs are distinct in - # Postgres, so each unique constraint only applies to items of that kind. + # SQLite unique constraints, so each constraint only applies to items of that kind. UniqueConstraint('collection_id', 'file_group_id', name='uq_collection_file_group'), UniqueConstraint('collection_id', 'zim_id', 'zim_entry', name='uq_collection_zim_entry'), UniqueConstraint('collection_id', 'url', name='uq_collection_url'), diff --git a/wrolpi/files/lib.py b/wrolpi/files/lib.py index ee2f06b6..2ecfbc3c 100644 --- a/wrolpi/files/lib.py +++ b/wrolpi/files/lib.py @@ -74,7 +74,7 @@ def sanitize_filename_surrogates(path: pathlib.Path) -> pathlib.Path: on disk to replace them with underscores. Linux filesystems store filenames as bytes. Python represents invalid UTF-8 - sequences as surrogates. These surrogates cannot be stored in PostgreSQL. + sequences as surrogates. These surrogates cannot be stored in the database. Returns the (possibly new) path. """ @@ -1057,7 +1057,7 @@ def search_files(search_str: str, limit: int, offset: int, mimetypes: List[str] @param mimetypes: Only return files that match these mimetypes. @param model: Only return files that match this model. @param tag_names: A list of tag names. - @param headline: Includes Postgresql headline if True. + @param headline: Includes FTS search headlines if True. @param months: A list of integers representing the index of the month of the year, starting at 1. @param order: Used to change results from most relevant to recently viewed. @param url: Filter by URL using case-insensitive partial match (ILIKE).