Is a firewall enough of a security measure for an Ubuntu server that hosts a website?

Is a firewall enough of a security measure for an Ubuntu server that hosts a website?

Given the technologies you want to use you want to create a dynamic database-backed website without having any experience with this. This kind of setup is typical for easy too exploit sites: database-backed often allows SQL injection, insecure uploads might allow code execution etc. The normal packet filter firewall on Linux will not protect against any of these application-level attacks, i.e. a firewall is not enough of a security measure.

With the level of experience you currently have I strongly recommend to not create some dynamic application which is accessible (and potentially exploitable) by anybody. If this is just for your own or some selected users you might try to password protect the site using the established mechanism the web server has (i.e. htpasswd or similar) to at least limit the attack surface by limiting who can access your website.

I'd also appreciate a book/website recommendation for Ubuntu and security complete beginners

To learn more about web security you might start with the Top 10 Web Application Security Risks. In general, this is unfortunately a fairly complex topic so don't expect to be quickly sufficiently familiar with it.

A firewall is never enough, it is the bare minimum. Then having an IDS of some sort is desirable. For example if your SSH port is exposed you should block brute-force attacks, even if you have a strong password. A typical server on the Internet is probed, attacked hundreds, thousands of times a day. I know, from all the alerts I receive in a single day and just by reading the logs. By the way, security can easily become a full-time occupation. And if you have logs but never read them, you could miss something.

If you are going to build a website from scratch I think the biggest danger comes from your own code. Your biggest enemy is you, if you don't know what you are doing. For example if your code allows SQL injections, then ufw will not protect you. Using a framework should help you avoid some rookie mistakes but does not guarantee quality of code. You need to learn best practices and how to write secure code. The framework will not teach you that.

Since you've mentioned Python I suggest pylint to test the quality of your code. There are other tools, like Bandit or Mypy for more specific checks.

A WAF (web application firewall) could be beneficial too but will require some tuning to be effective without being too restrictive.

There are lots of things you can do to reduce your attack surface. Google: "Linux hardening". If I had to recommend a book it would be Hacking exposed for a comprehensive overview.

One important thing is to keep your system up-to-date. Vulnerabilities are found all the time, and sometimes 0days too so you have to react quickly to download an upgrade or a patch (one recent example that comes to mind is Exim). So I strongly advise to subscribe to a few mail lists, websites or blogs about computer security to keep on top of news.

Equifax was hacked due to a flaw that had been patched a few months earlier. Their procrastination cost them dearly. Not maintaining your system increases the risk considerably. All it takes is one exploitable flaw.

Finally, I would advise you to pentest yourself. To test for SQL injections SQLmap is a great tool. But to achieve best results you need to understand how the tools work, just running them with default options will most of the time not suffice to find flaws (unless the site is very poorly coded). Sometimes, webmasters leave sensitive files on their server like SQL backups, because they forgot to delete the file after restoring a database. A directory listing could reveal the presence of files that should not be there.

Many websites have a phpmyadmin directory, and no protection whatsoever against brute-force attacks. So a hacker could gain access to your database this way. If you really want to have phpmyadmin on the server, at least don't use a predictable directory name, and restrict access so that it's not exposed to the whole word for zero benefit.

Ingress: Your website will be open to the world on tcp ports 80 and 443. You may also need to open up some other ports to allow you to manage the website (tcp port 22 for ssh for example, although you can limit the source to your management station). That means your webserver will be open to application level attacks on those ports. So test those ports for application level vulnerabilities.

Egress: If someone manages an application level attack against your webserver they can trick it into making an outbound connection to allow remote control. So it is good to limit egress connections from your webserver.

You will probably need egress port 53 (DNS). You may need some egress to grab patch updates (ideally you can make the destination IPs specific). Depending on your application you may need some egress access to access data or authentication resources.