PostgreSQL has 2 template databases: template0 that can't be modified, and template1 that is modifiable and is used to create every new database.
So I was playing with privileges, granting and revoking, and it caught my attention that, at least in my Docker image (as well as locally installed PostgreSQL), both template database have the same access privileges.
If I read this correct, it is giving connect privilege to both postgres default user and public role.
-- output is simplified
postgres=# \l
List of databases
Name | Owner | Access privileges
template0 | postgres | =c/postgres +
postgres=CTc/postgres
template1 | postgres | =c/postgres +
| postgres=CTc/postgres
Yet I know for sure that trying to connect to template0 will fail with
FATAL: database "template0" is not currently accepting connections.
I did some digging, th catalog pg_database has datallowconn property and in a description it says
it is used to protect the template0 database from being altered.
It might be an answer, but I'm not sure. I mean it's just a catalog, I think it stores data about object, I'm not sure if it can affect the behaviour of an object in any way.
So the ultimate question is - why can't we connect to template0?
The value false in the datallowconn field in pg_database is the only reason that prevents you from connecting to the template0 database. You can remove this lock by simply update the value as Postgres super user:
UPDATE pg_database SET datallowconn = TRUE WHERE datname = 'template0';
Now, you can connect to template0 by:
psql -Upostgres -dtemplate0
But you better not be doing that, of course. The postgres developers will have thought of something when they blocked access. If you corrupt the template databases, it's hard to create a new database.
Related
initially I have
Role name | Attributes | Member of
------------+------------------------------------------------------------+-----------
hezhenghao | Create DB | {}
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
and I typed
postgres=# REASSIGN OWNED BY hezhenghao to postgres
postgres-# ;
REASSIGN OWNED
postgres=# REASSIGN OWNED BY hezhenghao to postgres; REASSIGN OWNED
postgres=# DROP OWNED BY hezhenghao;
DROP OWNED
postgres=# DROP USER hezhenghao;
DROP ROLE
Now there is only one user
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
However when I type psql in terminal, I still got asked to Password for user hezhenghao:
and then I would end up with psql: FATAL: password authentication failed for user "hezhenghao"
I am new to postgres so I don't really understand what's going on here. Can someone help me with this?
If you don't specify a user with -U then psql will default to the username of the user currently logged in. In this case, it sounds like that user is hezhenghao. Use -U postgres to log in as the postgres user.
I can't seem to access my superuser account for my posgresQL database.
Using the command:
psql -U postgres
I sucessfully login into the user 'postgres'. However, this is not the default superuser. Doing:
=# \du
I get:
List of roles
Role name | Attributes | Member of
-----------+-------------------------------------+-----------
pgsql | Superuser, Create DB | {}
postgres | Create role, Create DB, Replication | {}
So 'pgsql' appears to be my default superuser.
When trying:
psql -U pgsql
I get the following error:
psql: FATAL: database "pgsql" does not exist
I changed the pg_hba.conf file to the following:
# Database administrative login by Unix domain socket
local all all trust
and also tried:
# Database administrative login by Unix domain socket
local all pgsql trust
but I still get the same error regardless, that database 'pgsql' does not exist.
Any help would be greatly appreciated, I need to be able to access the database's superuser.
just define database:
psql -U pgsql -d postgres
if you get error that postgres database does not exist, connect as postgres and list databases with \l
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------+-----------
postgres | Superuser, Create role, Create DB, Replication | {}
shorturl | Superuser | {}
postgres=# create database shorturl;
CREATE DATABASE
postgres=# \c shorturl;
You are now connected to database "shorturl" as user "postgres".
shorturl=#
My preference was to use database shorturl being the user shorturl and not postgres. How do I change the same?
Thanks in advance.
When you display the psql online help by entering \? you can see:
Connection
\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}
connect to new database (currently "postgres")
So you need to use:
\c shorturl shorturl
Another option, if you're already connected to database shorturl, is the command:
SET ROLE shorturl;
The benefits of that command are that it's not tied to psql, and that you can change user "midstream" of your work.
I did not know that template0 and template1 database templates are required in order to create empty databases. I deleted them in order to clear up postgres. Now I'm not able to create any new database. Gives me this error :
ERROR: template database "template1" does not exist
What can I do to get things going once again. I'll be very thankful for any help.
Luckily I had postgres database preserved because it was required for the postgres user to log into psql. Thus, created a template0 and template1 database :
create database template0 TEMPLATE postgres;
and same for template1. Then executed :
update pg_database set datistemplate=true where datname='template0';
for both databases to stop myself from accidentally deleting these templates again.
Everything works fine now :)
On my CentOS 7 box, I was not so lucky as to still have a database to connect to. However:
su postgres -c "initdb /var/lib/pgsql/data"
(as root) created a template0 and template 1 to work with.
For postgres 12.3 the following worked for me.
I deleted template1 not knowing what it was. I was able to create it from template0. You could also create it from postgres.
createdb -T template0 template1
createdb -T postgres template1
This is suggested in the docs -
template1 and template0 do not have any special status beyond the fact that the name template1 is the default source database name for CREATE DATABASE. For example, one could drop template1 and recreate it from template0 without any ill effects.
https://www.postgresql.org/docs/current/manage-ag-templatedbs.html
on my debian machine, i upgraded some clusters to version 11.
the template[01] databases on the target cluster have been dropped, rendering me with the ones from the older versions.
as root, i created a new cluster with pg_createcluster.
as user postgres:
dump the databases of the new cluster with pg_dumpall (with the --clean flag).
drop the new cluster.
import the resulted source in your cluster with psql.
i would remove the drop role postgres and creation of the same.
best regards,
alex
$ psql postgres
postgres=# \dn
List of schemas
Name | Owner
--------------------+----------
information_schema | postgres
pg_catalog | postgres
pg_toast | postgres
pg_toast_temp_1 | postgres
public | student
(5 rows)
When I log in to psql with user postgres, it shows that schema public is owned by user student. However, when I log in to psql with user student:
$ psql student
student=> \dn
List of schemas
Name | Owner
--------------------+----------
information_schema | postgres
pg_catalog | postgres
pg_toast | postgres
pg_toast_temp_1 | postgres
public | postgres
(5 rows)
It shows that schema public is owned by user postgres.
How can I get the ownership of schema public transferred to user student if the user with privileges to do so thinks that it's already done?
This is a misunderstanding. You are logging into two different databases.
When running
$ psql postgres
postgres is the name of the database. With default configuration the name of the database user is derived from the name of the system user using ident authentication automatically. The only parameter is assumed to be the database name. You do not want to change anything in the database postgres, it's a system database for maintenance tasks.
The other database is named student. Each database has a schema public with its respective owner.
Read the manual for psql or try a lowly man psql.
To transfer ownership of the schema public in the database student, log in as superuser:
psql -U postgres student
Or as operating system user postgres, just:
psql student
And run:
ALTER SCHEMA public OWNER TO student;
Details in the manual once more.