{"id":20479782,"url":"https://github.com/rafaeldavish/linux-server-configuration","last_synced_at":"2025-09-03T00:33:55.273Z","repository":{"id":143950497,"uuid":"131679040","full_name":"RafaelDavisH/Linux-Server-Configuration","owner":"RafaelDavisH","description":" Baseline installation of a Ubuntu Linux distribution on a virtual machine and prepared to host web applications, including updates installations, securing it from attack vectors and installing/configuring web and database servers.","archived":false,"fork":false,"pushed_at":"2018-05-01T05:21:37.000Z","size":137,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-16T03:51:38.658Z","etag":null,"topics":["apache2","aws-lightsail","flask-application","google-api","json","json-api","linux-server","postgresql","python-2-7","sqlalchemy"],"latest_commit_sha":null,"homepage":"https://quotes.rafaeldavis.me","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RafaelDavisH.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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-05-01T05:17:08.000Z","updated_at":"2018-05-01T05:27:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"d6a69bfd-7f81-4dc5-8815-04668b4f268c","html_url":"https://github.com/RafaelDavisH/Linux-Server-Configuration","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RafaelDavisH%2FLinux-Server-Configuration","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RafaelDavisH%2FLinux-Server-Configuration/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RafaelDavisH%2FLinux-Server-Configuration/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RafaelDavisH%2FLinux-Server-Configuration/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RafaelDavisH","download_url":"https://codeload.github.com/RafaelDavisH/Linux-Server-Configuration/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242049277,"owners_count":20063538,"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":["apache2","aws-lightsail","flask-application","google-api","json","json-api","linux-server","postgresql","python-2-7","sqlalchemy"],"created_at":"2024-11-15T15:47:34.049Z","updated_at":"2025-03-05T15:22:48.373Z","avatar_url":"https://github.com/RafaelDavisH.png","language":null,"readme":"# Linux Server Configuration\nBaseline installation of a Ubuntu Linux distribution on a virtual machine and prepared to host web applications, including updates installations, securing it from attack vectors and installing/configuring web and database servers.\n\nThe following instructions are written specifically for hosting a web application called [Pot Of Quotes](https://quotes.rafaeldavis.me) on an Amazon Lightsail instance.\n\n### Server Specifics\n\n- IP Address: _54.218.182.68_\n- SSH port: _2200_\n- URL: _https://quotes.rafaeldavis.me_\n\n### INSTRUCTIONS\n\n  **Get your server Ready**\n\nI. Ubuntu Linux server instance on [Amazon Lightsail](https://lightsail.aws.amazon.com/).\n\n  * Create an instance.\n\n  \u003cimg src=\"assets/create_instance.png\"\u003e\n\n  * Login to the server's terminal.\n\n  \u003cimg src=\"assets/servers-terminal.png\"\u003e\n\n\u003e ---\n\nII. Update all currently installed packages.\n\n  `$ sudo apt-get update`\n\n  `$ sudo apt-get upgrade`\n\n  * Install finger package.\n\n  `$ sudo apt-get install finger`\n\n\n  * To connect to your server via your terminal you must download your default private key from the `Account page`.\n\n  * **Recommendation**: _Create new SSH Key and name it whatever you want and can remember later._\n\n  \u003cimg src=\"assets/ssh-keys.png\"\u003e\n\n  \u003cimg src=\"assets/ssh-keys-page.png\"\u003e\n\n  * Make sure your downloaded SSH Key is placed inside: `~/.ssh/`. The SSH Key will have the ` .pem` suffix.\n\n\u003e ---\n\nIII. Change the SSH port from **22** to **2200**.\n\n  `$ sudo nano /etc/ssh/sshd_config.`\n\n  * Change port 22 to 2200\n\n  * Look for the line where it says `PasswordAuthentication yes` and change yes to **no**. Now all users will be forced to to log in using a key pair.\n\n  `$ sudo service ssh restart`\n\n  * Now you can connect via your local terminal with the following:\n\n  `ssh -i ~/.ssh/name_you_created.pem ubuntu@XX.XXX.XXX.XX -p2200`\n\n\u003e ---\n\nIV. Configure the _Uncomplicated Firewall_ (UFW) to only allow incoming connections for SSH(port 2200), HTTP(port 80), and NTP(port 123).\n\n  `$ sudo ufw default deny incoming`\n\n  `$ sudo ufw default allow outgoing`\n\n  `$ sudo ufw allow 2200/tcp`\n\n  `$ sudo ufw allow 80/tcp`\n\n  `$ sudo ufw allow 123/udp`\n\n  `$ sudo ufw enable.`\n\n  * Verify the ports that are allowed and denied.\n\n  `$ sudo ufw status`\n\n\n```\n      To                         Action      From\n    --                         ------      ----\n    2200/tcp                   ALLOW       Anywhere                  \n    80/tcp                     ALLOW       Anywhere                  \n    123/tcp                    ALLOW       Anywhere                  \n    22                         DENY        Anywhere                  \n    2200/tcp (v6)              ALLOW       Anywhere (v6)             \n    80/tcp (v6)                ALLOW       Anywhere (v6)             \n    123/tcp (v6)               ALLOW       Anywhere (v6)             \n    22 (v6)                    DENY        Anywhere (v6)\n```\n\nV. Creating a new user account named **grader**.\n\n  `$ sudo adduser grader`\n\n\u003e ---\n\nVI. Give **grader** the permission to **sudo**.\n\n  `$ sudo nano /etc/sudoers.d/grader`\n\n  * Type the following inside the file:\n\n  `grader ALL=(ALL) NOPASSWD:ALL`\n\n  * Save file (control X, Type `y`, and press enter/return).\n\n\u003e ---\n\nVII. Create an SSH key pair for **grader** using the **ssh-keygen** tool.\n\n  * On your local terminal (not connected to your server) create a SSH key pair.\n\n  `$ ssh-keygen -f ~/.ssh/name_you_created.rsa`\n\n  * You will be asked to enter a passpharse.\n\n  * `ssh-keygen` will generated two files.\n\n  `name_you_created` and `name_you_created.pub`\n\n  * Copy the `name_you_created.pub` content.\n\n  `$ cat ~/.ssh/name_you_created.pub`\n\n  * Go back to your AWS Lightsail server terminal to create `.ssh` directory and file named `authorized_keys`.\n\n  `$ cd /home/grader`\n\n  `$ mkdir .ssh`\n\n  `$ nano .ssh/authorized_keys`\n\n  * Paste the content of your `name_you_created.pub` into the `authorized_keys` file. Save the file.\n\n  * Change the permissions for the directory and file.\n\n  `$ chmod 700 .ssh`\n\n  `$ chmod 644 .ssh/authorized_keys`\n\n  * Now you can connect via your local terminal as `grader`.\n\n  `$ ssh -i ~/.ssh/name_you_created grader@XX.XXX.XXX.XX -p2200`\n\n  * Enforce the key-based authentication.\n\n  `$ sudo nano /etc/ssh/sshd_config`\n\n  * Look for the line that says `PasswordAuthentication`, make sure it has **no** not yes.\n\n  * Restart ssh service.\n\n  `$ sudo service ssh restart`\n\n\u003e ---\n\nVIII. Configuring the local timezone to UTC.\n\n  `$ sudo dpkg-reconfigure tzdata`\n\n  * Select `none of the above` and then `UTC`.\n\n\u003e ---\n\nXI. Installing and configuring Apache to serve a Python mod_wsgi application.\n\n  * **If you are building your project with Python 3, you will need to install the Python 3 mod_wsgi package on your server:**\n\n    `$ sudo apt-get install libapache2-mod-wsgi-py3`.\n\n\n  `$ sudo apt-get install apache2`\n\n  * Installing the `mod_wsgi` package (a tool that allows Apache to serve Flask applications) along with `python-dev` (a package with header files required when building Python extensions) using the following command:\n\n  `$ sudo apt-get install libapache2-mod-wsgi python-dev`\n\n  * Enable `mod_wsgi`.\n\n  `$ sudo a2enmod wsgi`\n\n\u003e ---\n\nX. Installing and configuring PostgreSQL:\n\n  `sudo apt-get install postgresql`\n\n  * Creating a new database user named `catalog` that has limited permissions to your catalog application database.\n\n  * Postgres will create a user named `postgres`.\n\n  `$ sudo su - postgres` and connect to database system `$ psql`.\n\n  `~$ CREATE USER catalog WITH PASSWORD password;`\n\n  `~$ CREATE DATABASE catalog WITH OWNER catalog;`\n\n  `~$ \\q` to exit `psql`\n\n\u003e ---\n\nXI. Install `git`.\n\n  `sudo apt-get install git`\n\n  * Create a directory named 'catalog' inside `/var/www/`.\n\n  `$ sudo mkdir /var/www/catalog`\n\n  `$ cd catalog`\n\n\u003e ---\n\nXII. Cloning and setting up Flask Application from the GitHub repository.\n\n  * Copy the Flask Web App project's clone link from GitHub.\n\n  `$ git clone [GitHub Repository link] catalog`\n\n  * The full PATH for the app should look like this:\n\n  `/var/www/catalog/catalog(app directory)/[GitHub Repository files]`.\n\n\u003e ---\n\nXIII. Setting up the server to function correctly when visiting on a browser.\n\n  * **Get out of the app directory one step back**\n\n  `$ cd .. `\n\n  * Create a `.wsgi file`.\n\n  `$ sudo nano catalog.wsgi`\n\n  * Include the following content inside `catalog.wsgi` file.\n\n  ```\n\n  activate_this = '/var/www/catalog/catalog/venv/bin/activate_this.py'\n  execfile(activate_this, dict(__file__=activate_this))\n\n  #!/usr/bin/python\n  import sys\n  import logging\n  logging.basicConfig(stream=sys.stderr)\n  sys.path.insert(0,\"/var/www/catalog/\")\n\n  from catalog import app as application\n  application.secret_key = 'supersecretkey'\n\n  ```\n  --\u003e ** If your app is based on Python2.7 you must have `#!/usr/bin/python2.7` above `import sys`.** \u003c--\n\n  * Move to the app directory.\n\n  `$ cd catalog`\n\n  * Change the `application.py` to `__init__.py`.\n\n  `$ mv application.py __init__.py`\n\n  * Edit `__init__.py`.\n\n  `$ sudo nano __init__.py`\n\n  * Change `app.run(hots='0.0.0.0', port=8000)` to `app.run()`\n\n  * In order for Google signin to work **Authorized JavaScript Origins** and **Authorized redirect URIs** must be updated.\n\n  * Log in into Google APIs console to edit your credentials.\n\n  **Google signing will not work properly sometimes by using the raw IP address. To make sure it works well it's recommended to have a domain name where you can have a subdomain for your app that points to your server's IP address.**\n\n  * Add your app domain address for **Authorized JavaScript origins.**\n\n  _https://yourappdomain.com_\n\n  * Add the **Authorized redirect URIs.**\n\n  _https://yourappdomain.com/login_\n\n  _https://yourappdomain.com/gconnect_\n\n  _https://yourappdomain.com/oauth2callback_\n\n  * Save file and download the `JSON` file.\n\n  * Open the `JSON` file and copy its content.\n\n  * Add or edit `client_secrets.json`. The file must be inside the app directory. `var/www/catalog/catalog/`.\n\n  **Example**\n\n  ```json\n\n    {\"web\":{\n  \t\"client_id\":\"XXXXXXXXXXXXXXXXXXXX\",\n  \t\"client_secret\": \"XXXXXXXXXXXXXXX\",\n  \t\"project_id\":\"XXXXXXXXXXXXXXXX\",\n  \t\"token_uri\":\"https://accounts.google.com/o/oauth2/token\",\n  \t\"auth_provider_x509_cert_url\":\"https://www.googleapis.com/oauth2/v1/certs\",\n  \t\"redirect_uris\":[\"https://yourappdomain.com/login\",\"https://yourappdomain.com/gconnect\",\"https://yourappdomain.com/oauth2callback\"],\n  \t\"javascript_origins\":[\"https://yourappdomain.com\"]}}\n\n  ```\n\n  * You need to add `\"client_secret\":\"XXXXXX\",` to the `client_secrets.json` as shown in the above example code.\n\n  * Edit `__init__.py` to properly find `client_secrets.json`.\n\n  `$ sudo nano __init__.py`\n\n  * Change the path for `client_secrets.json` in the following lines:\n\n  ```python\n\n  CLIENT_ID = json.loads(\n  open('/var/www/catalog/catalog/client_secrets.json', 'r').read())['web']['client_id']\n\n  ```\n\n  ```python\n\n  try:\n      # Upgrade the authorization code into a credentials object\n      oauth_flow = flow_from_clientsecrets('/var/www/catalog/catalog/client_secrets.json', scope='')\n      oauth_flow.redirect_uri = 'postmessage'\n      credentials = oauth_flow.step2_exchange(code)\n  ```\n\n  * The following line needs to be changed in `__init__.py` and in `database_setup_app.py`  to connect to the new database with `postgresql`.\n\n  ```python\n\n    engine = create_engine('postgresql://catalog:password@localhost/catalog')\n\n  ```\n\n  **Notice that when `catalog` user was created the word `password` was given as password. If you gave it a different password, make sure to use that instead.**\n\n\n  * Install `pip` if isn't installed already.\n\n  `$ sudo apt-get install python-pip`\n\n  * Install and start the virtual machine.\n\n  `$ sudo pip install virtualenv`\n\n  `$ sudo virtualenv venv`\n\n  `$ sudo chmod -R 777 venv`  \n\n  `$ sudo venv/bin/activate`\n\n  * Install the dependencies.\n\n  `$ pip install httplib2`\n\n  `$ pip install requests`\n\n  `$ pip install --upgrade oauth2client`\n\n  `$ pip install sqlalchemy`\n\n  `$ pip install flask`\n\n  `$ pip install psycopg2`\n\n  * Deactivate the virtual environment.\n\n  `$ deactivate`\n\n  * Set up and enable a virtual host by creating a file named `catalog.conf`.\n\n  `$ sudo nano /etc/apache2/sites-available/catalog.conf`\n\n* Paste the following code and save the file.\n\n```\n\u003cVirtualHost *:80\u003e\n    ServerName [www.yourappdomain.com]\n    ServerAdmin [your_admin_email@yours.com]\n    WSGIScriptAlias / /var/www/catalog/catalog.wsgi\n    \u003cDirectory /var/www/catalog/catalog/\u003e\n        Order allow,deny\n        Allow from all\n    \u003c/Directory\u003e\n    Alias /static /var/www/catalog/catalog/static\n    \u003cDirectory /var/www/catalog/catalog/static/\u003e\n        Order allow,deny\n        Allow from all\n        Options -Indexes\n    \u003c/Directory\u003e\n    ErrorLog ${APACHE_LOG_DIR}/error.log\n    LogLevel warn\n    CustomLog ${APACHE_LOG_DIR}/access.log combined\n\u003c/VirtualHost\u003e\n```\n\n* Enable the virtual host.\n\n`$ sudo a2ensite catalog`\n\n* The following prompt will be returned.\n\n```\n\nEnabling site catalog.\nTo activate the new configuration, you need to run:\nservice apache2 reload\n\n```\n\n`$ sudo service apache2 reload`\n\n* Disable the default Apache site.\n\n`$ a2dissite 000-default.conf`\n\n* The following prompt will be returned.\n\n```\n\nSite 000-default disabled.\nTo activate the new configuration, you need to run:\nservice apache2 reload\n\n```\n\n`$ sudo service apache2 reload`\n\n### Hooray! Your App should be working by now. Enter your app domain in the browser.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafaeldavish%2Flinux-server-configuration","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frafaeldavish%2Flinux-server-configuration","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafaeldavish%2Flinux-server-configuration/lists"}