Setting up and securing a new server for self-hosting web applications can be a daunting task. This repo contains bash scripts for automating the process!
The scripts in this repo are intended to set up and secure a new Ubuntu server for self-hosting web applications. Running the setup.sh script from the repo's root will copy the server's configuration variables (defined in the .env file) to the server and run all the following setup scripts:
-
configure-firewall.sh- Configures theufwfirewall to rate limit SSH connections and allow HTTP/HTTPS connections. -
configure-ssh.sh- Disables password authentication and only allow connections via SSH keys. -
create-user.sh- Creates a new, non-root user with their own home directory, bash shell, and sudo privileges. The username is taken from the.envfile. -
install-fail2ban.sh- Installs and configuresfail2banto block brute force SSH attacks. -
install-lazy-vim.sh- Installs the base LazyVim requirements and clones the starter configuration to the root and non-root user's home directories. -
install-zsh.sh- Installs ZSH and sets it as the default shell for the non-root user. Also copies the.zshrcand.gitconfigfiles from the dotfiles repo to the non-root user's home directory. This is optional and can be customized by setting theDOTFILES_REPOvariable in the.envfile or skipped entirely by setting it to an empty string (e.g.DOTFILES_REPO=""). -
setup-db-backups.sh– Sets up automated database backups for PostgreSQL usingrcloneto periodically save backups to a remote server. This is optional and can be enabled by setting all of thePOSTGRES_-prefixed variables in the.envfile, or skipped entirely by settingPOSTGRES_LOCAL_BACKUP_DIRto an empty string (e.g.,POSTGRES_LOCAL_BACKUP_DIR=""). For backups to work, it is assumed that (1) you have a local PostgreSQL instance running on your server at127.0.0.1:5432, and (2) you have anrcloneremote configured for backups. Setting up the remote must be done manually by connecting to the server and runningrclone configafter thesetup.shscript has completed successfully. See the Configuringrclonesection below for more details. -
upgrade-packages.sh- Upgrades all installed packages.
- Copy the
.env.examplefile to.envand fill in the values.
cp .env.example .env- Run the setup script.
bash setup.sh- The server is set up and ready to use! You can connect to the server with:
ssh ${YOUR_USERNAME}@${YOUR_SERVER_IP}- It is assumed that the server is already set up for SSH connections. This is usually done via the hosting provider on server creation. See SSH Key Creation section below if you need to do this manually.
- Scripts must be ran as the root user to avoid needing to enter a password for sudo.
- Last tested on
Ubuntu 24.04.3 LTS.
To verify that password authentication is disabled, you can try signing in without SSH keys.
ssh ${YOUR_USERNAME}@${YOUR_SERVER_IP} -o PubkeyAuthentication=noYou should see a message like this:
Permission denied (publickey).If you need to create a new SSH key pair, run the ssh-keygen command:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -C "${your_email@example.com}"Optionally, you can add the public key to the server manually if your hosting provider does not support adding SSH keys to the server during creation. Run the ssh-copy-id command:
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@${YOUR_SERVER_IP}To connect to your server with a custom domain name, add an A record to your DNS records that points your custom domain to your server's IP address.
For example, if your custom domain name is example.com and your server's IP address is 123.456.789.0, you would add the following A record to your DNS records.
| Type | Name | Content |
|---|---|---|
| A | example.com | 123.456.789.0 |
After DNS propagation, you can connect to your server using the custom domain:
ssh ${YOUR_USERNAME}@${example.com}To further simplify the connection process, you can add the following to your ~/.ssh/config file:
Host ${ANY_NAME_YOU_WANT}
HostName ${example.com}
User ${YOUR_USERNAME}
IdentityFile ~/.ssh/id_ed25519You can now connect using a custom name like this:
ssh ${ANY_NAME_YOU_WANT}To configure rclone, after the setup.sh script has completed successfully, first connect to your server via SSH:
ssh ${YOUR_USERNAME}@${YOUR_SERVER_IP}Then, run the following command to start an interactive configuration session:
rclone config- Be sure to create your own
client_idandclient_secretfor the Google Drive API. See: https://rclone.org/drive/#making-your-own-client-id - When prompted for scope, select option 1 (
Full access all files, excluding Application Data Folder). - If running on a headless server, you will need to authenticate on machine with a web browser. See: https://rclone.org/remote_setup/