What happens after a "DROP DATABASE postgres" - postgresql

I have a funny question about PostgreSQL database: What happens if the postgres database is dropped?
dropdb postgres worked.
createdb postgres worked too.
psql worked.
But I thought the users would be lost. Yet the old users are still there.
So where are the users stored for the database and which implications does dropping the postgres database have?

PostgreSQL metadata are stored in catalog tables, which are in the pg_catalog schema. These are accessible like regular views and tables.
There are shared system catalog tables which are shared between all databases. These tables are not affected when databases are dropped.
pg_authid, the table where the users are stored, is one of those shared catalogs. This is because in PostgreSQL, users don't belong to a database, but to the whole database cluster.
You can list all shared catalog tables like this:
SELECT relname FROM pg_class
WHERE relisshared AND relkind = 'r';
In the documentation you can find more information about the system catalogs.

When connecting to a Postgres server, you always need to specify which database you want to connect to.
When you set up a new server, you need something to connect to before you can run your first CREATE DATABASE statement.
That's all the postgres database is: a dummy database to use as a connection target for admin commands. There's no data in there, and you're free to drop it and use a different one instead (though whoever inherits your system will probably not thank you for it...).
As gil.fernandes said in his answer, server-wide objects like users are accessible from every database, but aren't stored inside any database in particular.

Related

How is the Postgres 'system database' attribute set or unset?

One of several databases in a Postgres 10.15 cluster has been set to be a system database. The mechanism that caused this is unknown, though it may have happened at the same time that the database was converted to a template by updating the pg_database table. The pg_database table does not have a setting to control whether or not a database is a system database, however, and I cannot find any documentation describing how to set (or unset, which is what I really want to do) the system database flag.
The idea of a “system database” is foreign to PostgreSQL, it is an artifact of pgAdmin.
PostgreSQL does have the notion of a “template database”, that is a database that is intended to serve s template in CREATE DATABASE. You turn a database to a template database with
ALTER DATABASE some_db IS_TEMPLATE TRUE;
For such a database it is also a good idea to forbid connections, because you can only use a database as template if nobody else is connected to it:
ALTER DATABASE some_db ALLOW_CONNECTIONS FALSE;

Create Postgres User with admin rights just for one database

How can I create a postgres user who has admin access only to one database but cannot inspect or interfere with other databases in the postgres instance? The use case is I'm creating a multitenant application
where each tenant gets his own database in the postgresql instance and can create schemas, tables etc and
perhaps use a few pg_tables to inspect his own database but not others.
cannot change the name of the database as it's controlled by me
EDIT: Added more constraints
That's fairly trivial:
CREATE DATABASE newdb;
GRANT CREATE ON DATABASE newdb TO newdba;
Add pg_hba.conf entries to allow newdba to connect to newdb only.

Minimum PostgreSQL requirement to view all databases?

Long time MariaDB/MySQL DBA, two weeks into being a Postgres DBA and I'm stumped...
I am creating a script that scans a host and ennumerates the databases but I'm having difficulty nailing down the least-privilege Postgres permissions. The script works fine when testing with SUPERUSER, but I'm not sure what permissions beyond USAGE it needs. It seems that any combination I come up with isn't working.
All you need to get a list of databases in a PostgreSQL cluster is a database user that can connect to one of the databases. Then you can run the SQL statement
SELECT datname
FROM pg_database
WHERE datallowconn;

Database named "postgres"

I've just set up Postgres for use by different users on my network. Every user has his own username/password/database, but when I connect to Pg I can also see a 'postgres' database (and even create tables etc). I tried to REVOKE access to that database from public but then it won't let me connect. What exactly is the postgres database and why is it needed? Can I disable it so that users only see the database(s) I've created for them?
The postgres database is created by default when you run initdb.
Quote from the manual:
Creating a database cluster consists of creating the directories in which the database data will live (...) creating the template1 and postgres databases. When you later create a new database, everything in the template1 database is copied. (...) The postgres database is a default database meant for use by users, utilities and third party applications.
There is nothing special about it, and if you don't need it, you can drop it:
drop database postgres;
You need to do that as a superuser of course. The only downside of this is that when you run psql as the postgres operating system user, you need to explicitly provide a database name to connect to
If you drop the postgres database you'll find a few things to be confusing. Most tools default to using it as the default database to connect to, for one thing. Also, anything run under the postgres user will by default expect to connect to the postgres database.
Rather than dropping it, REVOKE the default connect right to it.
REVOKE connect ON DATABASE postgres FROM public;
The superuser (usually postgres), and any users you explicitly grant rights to access the database can still use it as a convenience DB to connect to. But others can't.
To grant connect rights to a user, simply:
GRANT connect ON DATABASE postgres TO myuser;

Default databases in PostgreSQL

What are the default databases in PostgreSQL at the time of installation?
template1: the "default" database, which is copied when you perform "create database foo"
template0: the "minimal default" database, which serves essentially the same purpose, but typically used to create databases when restoring dumps which might already have the extra objects that are in template1, or to create a database that uses a different character encoding to the server default (template0 should only contain ASCII characters in strings)
postgres: an "administrative" database, which clients can assume exists to connect to merely to list which databases are available etc. Also, for example, pgAdmin will install the pg_agent schema in this database.
Apparently there is a database "postgres" that is created by default on each postgresql server installation.
It appears that it does not really have a well-defined purpose. According to the docs:
Creating a database cluster consists of creating the directories in
which the database data will live, generating the shared catalog
tables (tables that belong to the whole cluster rather than to any
particular database), and creating the template1 and postgres
databases. When you later create a new database, everything in the
template1 database is copied. (Therefore, anything installed in
template1 is automatically copied into each database created later.)
The postgres database is a default database meant for use by users,
utilities and third party applications.
(Source: http://www.postgresql.org/docs/8.2/static/app-initdb.html )