{"id":15930777,"url":"https://github.com/sripwoud/linux_server_config","last_synced_at":"2025-04-03T14:20:35.548Z","repository":{"id":104841068,"uuid":"157281127","full_name":"sripwoud/linux_server_config","owner":"sripwoud","description":"Full Stack Dev Project: set up a secure linux web server using a Digital Ocean droplet.","archived":false,"fork":false,"pushed_at":"2024-02-11T17:10:12.000Z","size":35,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-09T03:15:01.268Z","etag":null,"topics":["digital-ocean-droplet","droplet","flask","linux-server","ssh","udacity","udacity-fullstack-nanodegree","wsgi"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sripwoud.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-12T21:43:59.000Z","updated_at":"2023-04-07T17:02:29.000Z","dependencies_parsed_at":null,"dependency_job_id":"f0e46785-2d98-4b5c-b0a4-e7088c120675","html_url":"https://github.com/sripwoud/linux_server_config","commit_stats":null,"previous_names":["sripwoud/linux_server_config"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sripwoud%2Flinux_server_config","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sripwoud%2Flinux_server_config/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sripwoud%2Flinux_server_config/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sripwoud%2Flinux_server_config/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sripwoud","download_url":"https://codeload.github.com/sripwoud/linux_server_config/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247014514,"owners_count":20869376,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["digital-ocean-droplet","droplet","flask","linux-server","ssh","udacity","udacity-fullstack-nanodegree","wsgi"],"created_at":"2024-10-07T01:00:52.815Z","updated_at":"2025-04-03T14:20:35.374Z","avatar_url":"https://github.com/sripwoud.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Linux Server Configuration\nThis page explains how to set up a secure linux web server using a Digital\nOcean droplet. This server will then be used to deploy the [vinyls catalogue](https://github.com/Gry0u/vinyls_catalogue)\nI previously developed.  \n~~The address of the server I deployed is **http://104.248.253.240.xip.io/**~~\n## 1. Create the Digital Ocean Droplet\n1. On your local machine create RSA key pairs with the following command:  \n```\n$ ssh-keygen\n```\n2. [Create digital ocean droplet](https://www.digitalocean.com/docs/droplets/how-to/create/)  \nI chose the following configuration: 1 GB Memory / 25 GB Disk / FRA1 - Ubuntu 18.04 x64.  \nProvide the ssh `.pub` key you created at the previous step.\n3. [Log in to your droplet with ssh](https://www.digitalocean.com/docs/droplets/how-to/connect-with-ssh/):\n```  \n$ ssh -i /path/to/private/key root@ip.ad.dr.ess\n```\n\n## 2. Initial server set up\nAs explained in this [tutorial](https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04), there are a few basic initial configuration steps that should be taken over in order to secure the server:\n1. Create a new user:  \n```\n$ adduser username\n```\n2. Grant sudoer rights:\n```\n$ usermod -aG sudo username\n```\n4. Update and upgrade (keeping local existing configuring files, if asked):\n```\n$ apt update \u0026\u0026 apt upgrade\n```\n5. Enable external access via ssh for the newly created user by copying the ssh public key:  \n```\n$ rsync --archive --chown=username:username ~/.ssh /home/username\n```\n6. Change ssh port from 22 to 2200:\n```\n$ nano /etc/ssh/sshd_config\n```\nReplace `#port 22` by `port 2200`.  \n7. Restart:\n```\nservice ssh restart\n```\n8. ```exit```\n9. Log in as the new via ssh:\n```\nssh -i /path/to/private/sshkey username@ip.ad.re.ss -p 2200\n```\n10. Configure the firewall to only allow incoming connections for SSH (port 2200), HTTP (port 80), and NTP (port 123) and OpenSSH:\n```\n$ sudo ufw default deny incoming  # deny all incoming connections\n$ sudo ufw default allow outgoing # allow all outgoing connections\n$ sudo ufw allow OpenSSH\n$ sudo ufw allow 2200/tcp         # open port 2200 for ssh connection\n$ sudo ufw allow www              # open port 80 for HTTP requests\n$ sudo ufw allow 123/udp\n$ sudo ufw deny 22                # close this port as it was replaced by 2200\n$ sudo ufw enable\n$ sudo ufw status                 # should list all the rules you just set up\n```  \n11. Disable root login:\n```\n$ sudo nano /etc/ssh/sshd_config\n```  \nReplace `PermitRootLogin yes` by `PermitRootLogin no`.\n```\n$ service ssh restart  \n$ ssh -i /path/to/private/sshkey root@ip.ad.dr.ess -p 2200\n```\nShould not work anymore.  \n12. Configure Timezone to Use UTC  \n```\nsudo dpkg-reconfigure tzdata\n```  \nSelect `none of the above`.\n\n## 3. Install Apache web server  \n```\n$ sudo apt update  \n$ sudo apt install apache2\n```  \nCheck your website at http://ip.ad.dr.ess.\nYou should see the default apache 'it works' page.\n## 4. Install mod_wsgi\n```\n$ sudo apt install libapache2-mod-wsgi\n```    \n## 5. Install pip\nThe application I am deploying is written in python 2.7.\n```\n$ sudo apt install python-pip  \n```\nCheck with `pip --version` that the installation was successful.  \n## 6. [Install and configure git](https://git-scm.com/download/linux)  \n```\n$ sudo add-apt-repository ppa:git-core/ppa\n$ sudo apt update\n$ sudo apt-get install git\n$ git config --global user.name \"username\"\n$ git config --global user.email \"username@mail.com\"  \n```\nYou can check your settings with `git config -l`.\n## 7. PostgreSQL\n### 7.1 [Install](https://www.postgresql.org/download/linux/ubuntu/)   \n```\n$ sudo nano /etc/apt/sources.list.d/pgdg.list\n```  \n- Add `deb http://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main`  \n- Import the repository signing key  \n```\n$ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -\n```\n- Install\n```\n$ sudo apt-get update\n$ sudo apt install postgresql-10\n```\n### 7.2 Configure:\n- Create `catalog` role for the database:\n```\n$ sudo su - postgres\n$ psql\npostgres=# CREATE ROLE catalog WITH PASSWORD 'catalog';\npostgres=# ALTER ROLE catalog CREATEDB;\n```  \nYou can check with `\\du` that the catalog user has been created.\n- Quit and exit: `\\q `, `exit `.\n- Create catalog **user** and add to sudoers :\n```\n$ sudo adduser catalog\n$ sudo usermod -aG sudo catalog\n```\n- Log as `catalog` user and create the `catalog` database:\n```\n$ su - catalog\n$ createdb catalogue\n```\nYou can check with `\\l` that the database has been created.\n\n## 8. Deploy application  \n### 8.1 Set up the Flask app\n\n1. Create application directory:\n```\n$ sudo mkdir /var/www/catalog \u0026\u0026 cd /var/ww/catalog/\n```\n2. Clone application repository, renaming it 'catalog':\n```\n$ sudo git clone https://github.com/Gry0u/vinyls_catalogue.git catalog\n```\n3. Rename and edit `views.py`  \nChange\n```\napp.debug = True\napp.run(host='0.0.0.0', port=5000)\n```\nto\n```\napp.run()\n```\nAnd **give the absolute path of the client_json file when defining the CLIENT_ID variable (file isn't found otherwise!):**\n```\nCLIENT_ID = json.loads(\n    open('/var/www/catalog/catalog/client_secrets.json', 'r').read())['web']['client_id']\n```\n4. Edit `database_setup.py`, change the engine creation statement to:  \n`engine = create_engine('postgresql://catalog:catalog@localhost/catalog')`\n5. Add your server's IP address to your  authorized origins in your OAuth client ID settings (I use the [Google API](https://console.developers.google.com/))\n6. Update `client_secrets.json` in catalog/catalog accordingly (dowload file, then copy paste content). Check that the client_secret key\nis in the json file.\n7. Update login.html with your CLIENT ID if necessary\n8. [Create a python virtual environment](http://flask.pocoo.org/docs/0.12/installation/ )\n```\n$ sudo apt install python-virtualenv\n```\n9. Install required modules  \nIn catalog/catalog/:\n```\n$ sudo virtualenv venv  \n$ chown -R grader:grader catalog/\n$ . venv/bin/activate\n$ pip install --upgrade flask sqlalchemy httplib2 oauth2client requests  \n$ sudo apt install libpq-dev  \n$ pip install psycopg2\n```\n\n### 8.2 Set up and configure the virtualhost\n1. Create `/etc/apache2/sites-available/catalog.conf` and add the following lines:\n```\n\u003cVirtualHost *:80\u003e\n\t\tServerName your.server.ip.address\n\t\tServerAdmin you@mail.com\n\t\tWSGIScriptAlias / /var/www/catalog/catalog.wsgi\n\t\t\u003cDirectory /var/www/catalog/catalog/\u003e\n\t\t\tOrder allow,deny\n\t\t\tAllow from all\n\t\t\u003c/Directory\u003e\n\t\tAlias /static /var/www/catalog/catalog/static\n\t\t\u003cDirectory /var/www/catalog/catalog/static/\u003e\n\t\t\tOrder allow,deny\n\t\t\tAllow from all\n\t\t\u003c/Directory\u003e\n\t\tErrorLog ${APACHE_LOG_DIR}/error.log\n\t\tLogLevel warn\n\t\tCustomLog ${APACHE_LOG_DIR}/access.log combined\n\u003c/VirtualHost\u003e\n```\n2. Enable the virtual host:\n```\n$ sudo a2ensite catalog\n```\nAnd reload as prompted\n```\n$ sudo systemctl reload apache2\n```\n### 8.3 Create the .wsgi file\n```\n$ sudo nano /var/www/catalog/catalog.wsgi\n```\n- Add the following lines:  \n```\n#!/usr/bin/python\nimport sys\nimport logging\nlogging.basicConfig(stream=sys.stderr)\nsys.path.insert(0,\"/var/www/catalog/\")\n\nfrom catalog import app as application\napplication.secret_key = 'Add your secret key'\n```\n- Restart Apache: `sudo service apache2 restart`\n```\n$ sudo a2dissite 000-default.conf\n$ sudo service apache2 restart\n```\n\n\n\n**Enjoy your application by accessing directly to the IP address of your droplet (mine is listed at the very beginning) in your browser.**\n\n*Note: Unlike the initial application which was accessed locally, the deployed application (or more specifically the `catalog` back end database) is not populated beforehand with any genre, album or songs --\u003e it is completely clean and free to be filled!*\n\n# Resources\n- [Application](https://github.com/Gry0u/vinyls_catalogue) written in [Python 2.7](https://www.python.org/), leverages the[ Flask](http://flask.pocoo.org/) microframework.\n- Back-end built using the [PostgreSQL](https://www.postgresql.org/) database system together with the [SQLAlchemy](https://www.postgresql.org/) Python toolkit\n- Application deployed on a Linux Server hosted on a [Digital Ocean](https://www.digitalocean.com/) droplet, using an [Apache](https://httpd.apache.org/) server.\n## Tutorial and guides\n[How to Create a Droplet from the DigitalOcean Control Panel](https://www.digitalocean.com/docs/droplets/how-to/create/)  \n[Connect with SSH](https://www.digitalocean.com/docs/droplets/how-to/connect-with-ssh/)  \n[Initial Server Setup with Ubuntu 18.04](https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04)  \n[How To Deploy a Flask Application on an Ubuntu VPS](https://www.digitalocean.com/community/tutorials/how-to-deploy-a-flask-application-on-an-ubuntu-vps)\n[How To Secure PostgreSQL on an Ubuntu VPS](https://www.digitalocean.com/community/tutorials/how-to-secure-postgresql-on-an-ubuntu-vps)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsripwoud%2Flinux_server_config","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsripwoud%2Flinux_server_config","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsripwoud%2Flinux_server_config/lists"}