PostgreSQL beginner guide
knowledgepill.it
knowledgepill.it
However, the question where I struggled the most: how the hell do I set up a secure Postgres instance on some cloud VM or server? (I _really_ love those 2.50 bucks per month instances)
I spent a fair amount of time reading up on it, but it's still really easy to make a mistake in your `pg_hba.conf` or somehwere else. I remember disabling password based login, and just authenticating over SSH, and my server still got compromised after a day or two. 100% my fault - I think it was related to `COPY FROM/TO` being able to run arbitrary commands because I didn't understand that `postgres` is regarded as a superuser by the database.
I've been using managed services like Heroku Postgres and RDS ever since.
Point is: it would be of huge value to have a clear (but complete) overview of how to configure a Postgres instance so that it's secure in the basic sense. If that isn't possible (or very hard) then please let's collectively tell beginners to just use managed instances.
I still haven’t been compromised. Have I done something wrong?
In my case I was only made aware of the compromised VM because my hosting provider sent me very stern email about my server's IP netscanning their entire fricking address range.
Then see if it got compromised.
This means that your data either goes in plain text over the network, or might be vulnerable to a MITM attack (if you don't manage your certs correctly).
I also guess that you don't use SCRAM as the password hashing method, but rather MD5. That means that if someone is able to listen to the connection, they can do a replay attack using the password hash, as there is only 32 bits of entropy added to the hash from the server side. And once you have managed to do the replay attack you can issue arbitrary sql commands as that user.
Which is ok until about 5 seconds after you open the port to the world.
I'm also pretty sure that the upstream documentation warns against using the superuser for application access, so if you just create a regular database user protected by a reasonable password it will be as secure as any database exposed to a network can be; of course, exposing databases to the internet is something to be avoided in the first place.
non-mobile EDIT:
The above ignores TLS, which is generally a good idea if you want to make something accessible over the network.
A guide for beginners might be useful, but if you work with these things, it may be useful to learn how to approach security in general so that you will be able to learn how to secure anything, or at least know when you don't know enough.
In general, installing services securely requires the administrator to understand how the service is accessed by legitimate users and whether in doing so is potentially exposed to external access. If you just google for how-tos you're quite likely to find lots of bad advice that skips security considerations and takes you from A to B the fastest route.
The effort required is entirely dependent on your requirements; in most cases, avoiding exposure to the internet, patching your software and using strong passwords is enough, as it stops nearly all low-effort automated attacks.
For starters with any network-exposed service, you should understand that not exposing it to the internet in the first place means that the rest of your security measures will be challenged less; so if you can, limit access to internal networks and specific hosts with firewalls and ACLs.
If you have to expose a service to the internet, then you need authentication and authorization; anyone will be able to connect to the service, but the service should challenge them to identify themselves using secure credentials.
Once the user has access to your service, you'll want to limit what they can do with it. This requires reading the manual.
Lastly, you'll generally want to keep your software up-to-date; unpatched software may have bugs that allow attackers to bypass some of the security measures you have set up.
Any suggestions on how to get started with this?
What could work is something akin to a Wikipedia dive. Pick a system to set up and make note of as many concepts along the way as you can; For example, setting up a Postgres database involves networking (what does a "listen address" actually mean?), different kinds of authentication (eg. pg_hba md5, trust, and peer authentication options), OS users and database users (easy to get those two confused), among other things. One could also wonder why there's a database superuser, and what makes the system such that using it for application access it is a bad idea?
Then try thinking about potential ways of how all these things could interact to break a system. This can give you a lot of insight into how to secure systems against attackers.
For example, setting up Postgres to not authenticate users is not necessarily detrimental to the overall security of a system if everything is local and single-user, but makes the system extremely weak if any component on the host is exploitable from the outside.
So even if you really don't want to use passwords, you should at the very least use peer authentication where the database allows only specified OS users to connect such that any attacker must at least be able to access the system as one of those users.
Lastly, if you put a non-authenticating system on a network, it should not be surprising that anyone who happens to be able to poke at your network address can just waltz in without resistance. You'll at the very least want strong passwords, possibly with brute force detection to detect people trying to guess credentials. The IPv4 internet is only about 4 billion addresses, and automatically scanning through them for listening services is routine for attackers. :)
This is where your advice goes south, IMHO. The sysadmin can't think of every possible way his system can get compromised -- they are not paid for that, black-hat hackers are.
Instead of collecting settings from a hundred places that must be set correctly for production, and inventing ways the system can get compromised, the safe settings could be provided in one place: ideally in the default settings so they are impossible to miss, or in a list, such as Django's deployment checklist [1].
Not saying that Postgres doesn't provide such a list, although googling for "checklist site:postgresql.org" only resulted in a mailing list reply [2], with some points not trivial to follow. Please comment below if you know an official one.
[1]: https://docs.djangoproject.com/en/3.0/howto/deployment/check... [2]: https://www.postgresql.org/message-id/D960CB61B694CF459DCFB4...
I'm pretty sure most security breaches are caused by really basic configuration mistakes (or process failures). following a checklist can definitely be effective, but if you don't actually understand why you're configuring things as you are, you're likely to make mistakes elsewhere.
> I remember disabling password based login, and just authenticating over SSH, and my server still got compromised after a day or two.
This sentence in particular is hard to parse. Did you turn off password login in pg_hba.conf or in your sshd_config ?
PS: VPS box literally start being scanned/tested over standard ssh port minutes after being spin-up. It seem less frequent however to be attacked for specific postgreSQL vulnerabilities (but that might well be a new trend).
Specifically it seems to be giving them a domain name; I've had instances sit with few or no attempts against them as long as I do not assign a name.
It should not be publicly accessible to the world.
You could also tunnel it over ssh and map the port.
For me, it's the third result on DuckDuckGo for "PostgreSQL RDS"
Too expensive? Not as fun?
Asking as I am offering a similar service, hosted database.
simplesql.redbeardlab.com (not production ready)
That "or" is not exclusive.
Bit worried about the quality of the content, based on the quality of the proofreading.
I don't know why this feeling persists. The ability to proofread or write free of spellings is a skill completely unrelated to the underlying content. Complaining about the spelling just seems childish at this point. We live in a world full of mistakes and problems. Dealing with life despite of them is a fundamental life skill.
It's not about the ability, but the willingness. I think it would be amoral to tolerate those bums who externalise costs onto the reader. https://www.fourmilab.ch/documents/strikeout/
he doesn't write often, but it's advanced technical topic, I find it super useful and well explained.
But making it listen on an external IP does not inherently make it insecure, as long as you also have other firewall and user account controls.
> If you need remote access to the DB, then you need remote access
That's not a defence for teaching insecure practices. It's possible to configure Postgres for secure remote access.
Using md5 for password security seems like a red flag, and sure enough, the Postgres docs remind us that md5 should no longer be considered secure. [0] I don't think there's any verification of the server's fingerprint, either.
There's really no excuse here, as there's a quick and easy way to do it: SSH tunnels. [1]
> Most people in a normal setup would not have the database server ports directly exposed to the Internet
Not a safe assumption. Instances on Linode and, iirc, Digital Ocean, are not behind a cloud firewall, all ports are wide open to the Internet. (I think that's a bad move on the part of Linode and Digital Ocean, but that's not the point.)
> if you have the perspective that all servers are in the cloud, then you would also be expected to know how to keep them secure
If you already knew how to securely configure Postgres, you wouldn't need the tutorial.
> making it listen on an external IP does not inherently make it insecure, as long as you also have other firewall and user account controls
You still need to configure the crypto properly.
[0] https://www.postgresql.org/docs/current/auth-password.html
[1] https://www.postgresql.org/docs/current/ssh-tunnels.html
For those looking for similar Postgres related resources, I've found this handy Postgres Cheat Sheet [1] to be really useful.
Surely NoSQL + typescript is better for development (and potentially for performance).
Thoughts?
All my experiences were wonderful, especially its performance and powerful features like rule rewriting.
Also PostgREST is brilliant.
Given that postgREST exists, I don't see any reason to talk to postgres directly from a JS app.
It definitely allows for faster iteration, though. You can deploy a prototype or change very quickly without caring about this, which is pretty nice. But you need to keep track of that and pay the debt if you use the prototype.
Overall, I think it would not give or take much if we'd be using PostgreSQL+some JSON column for general data instead of CouchDB. You just need to know your stack and its drawbacks and work with them.
`db.collection('test').find({year:2020})` only returns rows with an integer value of 2020 and not a string value of "2020"...
What scares me more than anything else is lost / compromised / invalid data. That's hard to fix. The frontend code is straightforward to fix, relatively speaking.
You can then extract fields into their own columns over time, as you learn more about your domain. JSON support is pretty excellent.
No amount of work of coding will fix your data, if it is a mountain of inconsistent garbage.
If you care for the data you store, you'll have to take care of your data. ACID and the "rigidness" of schemata are tools for that, and to keep the complexity in check. It is much easier than accruing technical debt by having unstructured data and having later to figure out to make heads and tails of what you and your colleagues did at some arbitrary earlier time. (Not that crappy SQL designs don't have that problem).
If you don't care for your data, as you are in the beginning, why don't you create the DB then from scratch? You can use various editors to create the schemata from tools you are more comfortable with.
Don't work against the tool, and find the slider in your head to adjust your way of working.
At least in my experience the "philosophical" language-database pairing always ended up being much less important than the database own strength and weaknesses in regards to the problem being solved.
For me Postgres is the best default choice if you don't understand that well where your project/product is going (Not saying it isn't a good choice later on as well). Out of the box it handles pretty much every use case I encountered at least good enough for a long time without adding supplemental data stores or ugly hacks.
For me the difference in development barely matters. Locally schema changes are pretty much friction-less with the right tooling, and in production the problem is usually not changing the schema, but the existing data. The latter being a pain in any tech I have used so far, because often it is not even an engineering challenge but a matter of business decisions.
Most systems do not need no-SQL. The only reason to use no-sql is when you are allowing users to create completely dynamic form schemas and JSON and when your product is garbage and you need a "quick" db for prototyping.
That's not to mention that when your product grows and you are selling to "serious" corporations, they ask you to integrate with third-party data visualization / analysis software. They claim to support MongoDB/No-SQL in their marketing material, but virtually none of them do, and you are mapping back to SQL. That's when the cost of using no-SQL really hits, several years down the line.
Yep that's the stage the project was at.
Integrating the DB with grafana was a breeze though so that's definitely a benefit. I've personally never tried to hook up a MongoDB to Grafana, wonder if it's any easier.
First, the ideological thing: flexibility is an awful thing for user's data and logical relationships within it. The fact that with RDBMS you have to define your schema and follow it, makes many classes of erros that would have been corrupted data at operations to being exceptions at development: PostgreSQL just won't let you shoot yourself in the foot like that. And with pgtyped, which I'm growing to love, you don't even have to write any boilerplate: just write plain straightforward SQL, run verification against your test database, and get all of your types for free.
But that's not even the most important part; what I absolutely love about SQL is my ability to delegate huge amounts of work from my app server to my db server, saving a lot of latency and CPU. It may not be that critical for things when you just update one row in the 'users' table, but when you have O(n) updates and up, it's just great to be able to do things directly in the database.
And in rare occasions where you absolutely have to use non-structured data (or data with a lot of different data types that don't deserve their own columns), jsonb is useful and pretty damn fast if you think throught the schema and make use of the GIN indexes.
IMO, the strictness was in the right place (the source of truth), what was probably backwards is the team’s relative skill and tooling for adapting the solution. Which might make it wrong for the team, if it is otherwise right for the situation.
After getting used to it it wasn't so bad but the unclear error messages, abstractions and lack of types really made it a steep learning curve.
If the codebase was in typescript it would've saved a lot of time trying to sleuth out the documentation for an abstracted piece of code.
Postgresql and NodeJS is the best! being using it for years. Of course you got learn SQL or some kind of ORM to make it worth you while.