{"id":16719139,"url":"https://github.com/kgryte/linode-setup-notes","last_synced_at":"2025-09-05T23:51:10.250Z","repository":{"id":66159154,"uuid":"41605601","full_name":"kgryte/linode-setup-notes","owner":"kgryte","description":"How to setup Linode.","archived":false,"fork":false,"pushed_at":"2017-08-20T22:27:50.000Z","size":23,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-22T01:44:43.612Z","etag":null,"topics":["guide","linode","tutorial"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kgryte.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":"2015-08-29T19:58:44.000Z","updated_at":"2023-08-10T19:36:27.000Z","dependencies_parsed_at":"2023-02-21T02:16:10.820Z","dependency_job_id":null,"html_url":"https://github.com/kgryte/linode-setup-notes","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/kgryte%2Flinode-setup-notes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kgryte%2Flinode-setup-notes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kgryte%2Flinode-setup-notes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kgryte%2Flinode-setup-notes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kgryte","download_url":"https://codeload.github.com/kgryte/linode-setup-notes/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243719400,"owners_count":20336607,"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":["guide","linode","tutorial"],"created_at":"2024-10-12T21:40:32.847Z","updated_at":"2025-03-15T11:14:17.747Z","avatar_url":"https://github.com/kgryte.png","language":null,"readme":"# Linode Setup\n\n\u003e How to setup [Linode][linode].\n\nThe following are notes on how to setup [Linode][linode]. The initial setup steps have been mainly compiled from the [Linode][linode] getting started guides, which collectively provide a good starting point for basic configuration. \n\n1. [Provision](#provision)\n1. [Remote Access](#remote-access)\n1. [Basic Ubuntu Setup](#basic-ubuntu-setup)\n1. [Basic Security Setup](#basic-ubuntu-setup)\n1. [Reverse DNS](#reverse-dns)\n1. [Software](#software)\n1. [Sites](#sites)\n1. [References](#references)\n\n---\n\n## Provision\n\nTo provision a new [Linode][linode] server, see the getting started [guide][linode-getting-started]. After a few minutes, a [Linode][linode] server will be provisioned. This guide assumes you have chosen `Ubuntu 14.04 LTS` as your base image.\n\n\n---\n\n## Remote Access\n\nTo connect to a [Linode][linode] server,\n\n``` bash\n$ ssh root@\u003cyour_server_ip\u003e\n```\n\nwhere your server IP may be found via \n\n```\nLinodes --\u003e dashboard --\u003e Remote Access\n```\n\nYou will be prompted for the `root` password you created when deploying a new image to your [Linode][linode].\n\n\n---\n\n## Basic Ubuntu Setup\n\nTo set up your new server, do as follows...\n\n#### Hostname\n\nSet the server hostname. The hostname should be unique (similar to naming a person or pet). For example,\n\n``` bash\n$ echo \"myserver\" \u003e /etc/hostname\n$ hostname -F /etc/hostname\n```\n\nVerify that the hostname was set:\n\n``` bash\n$ hostname\n```\n\n\n#### Hosts\n\nSet the server's full-qualified domain name (FQDN) by updating the `/etc/hosts` file.\n\n``` bash\n$ sudo nano /etc/hosts\n```\n\nUpdate the `/etc/hosts` file to include your FQDN:\n\n```\n127.0.0.1 \tlocalhost.localdomain \tlocalhost\n127.0.0.1 \tubuntu\n\u003cyour_server_ip\u003e myserver.\u003cyour_domain\u003e \tmyserver\n\u003cyour_ipv6_ip\u003e myserver.\u003cyour_domain\u003e \tmyserver\n```\n\nwhere `\u003cyour_server_ip\u003e` is your server's IP address and `\u003cyour_domain\u003e` is a domain over which you have control; e.g., `example.com`.\n\nThe assigned FQDN should have a corresponding \"A\" record in DNS pointing to your server's IPv4 address and an \"AAAA\" record in DNS pointing to your server's IPv6 address. Doing so allows you to easily resolve your server when using, e.g., SSH.\n\n``` bash\n$ ssh myserver.\u003cyour_domain\u003e\n```\n\nFor more information, see the \"Adding DNS Records\" section in the Linode [guide][linode-hosting-website].\n\n\n#### Timezone\n\nSet the server timezone:\n\n``` bash\n$ dpkg-reconfigure tzdata\n```\n\nVerify that the date is correct:\n\n``` bash\n$ date\n```\n\n\n#### Update\n\nInstall any available updates and security patches:\n\n``` bash\n$ apt-get update\n$ apt-get upgrade --show-upgraded\n```\n\n---\n## Basic Security Setup\n\nTo setup basic security and protect the server from unauthorized access, do as follows...\n\n#### Two-Factor Authentication\n\nYou are encouraged to setup two-factor authentication when logging in to the Linode manager. From the Linode manager, navigate to\n\n```\nMy Profile --\u003e Password \u0026 Authentication --\u003e Two-Factor Authentication\n```\n\n\n#### User\n\nYou are recommended to never use `root` for day-to-day tasks. A `root` user has the ability to execute any command, including commands which could break your server. For most tasks, you can use an account having normal permissions and execute `superuser` commands using `sudo`. To add a new user,\n\n``` bash\n$ adduser \u003cyour_username\u003e\n```\n\nwhere `\u003cyour_username\u003e` if your desired user name. Add the user to the `sudo` group:\n\n``` bash\n$ usermod -a -G sudo \u003cyour_username\u003e\n```\n\nLogout from the server and then login with the new user:\n\n``` bash\n$ logout\n$ ssh \u003cyour_username\u003e@\u003cyour_server_ip\u003e\n```\n\n\n#### SSH\n\nSSH keys allow you to authenticate using a public-private key pair and remove the need for password-based authentication.\n\n__WARNING__: do __not__ complete the following steps from a publicly shared computer. Run the commands from your local computer.\n\n\n##### Generate SSH keys\n\nIf you have already generated SSH keys before (e.g., when configuring GitHub to use SSH), you can skip the following step. To generate SSH keys,\n\n``` bash\n$ ssh-keygen -t rsa -C \"\u003cyour_email_address\u003e\"\n```\n\nWhen prompted, create a strong password. If you use a Mac, the password can be added to your keychain.\n\n\n##### Copy the public key\n\nCopy the public key to the server using the secure copy command `scp` from your local computer.\n\n``` bash\n$ scp ~/.ssh/id_rsa.pub \u003cyour_username\u003e@\u003cyour_server_ip\u003e:\n```\n\nRemember the `:` at the end. Once copied to our Linode server, we need to create a new directory on that server to store the public key and set the appropriate permissions.\n\n``` bash\n$ mkdir .ssh\n$ mv id_rsa.pub .ssh/authorized_keys\n$ chown -R \u003cyour_username\u003e:\u003cyour_username\u003e .ssh\n$ chmod 700 .ssh\n$ chmod 600 .ssh/authorized_keys\n```\n\n##### Disable SSH password authentication\n\nIf you connect to your Linode from only one computer, you should disable password authentication and require that all users authenticate using key-based authentication. If you need to connect from multiple computers, you may want to keep password authentication enabled to prevent having to copy your private key to multiple computers.\n\n``` bash\n$ sudo nano /etc/ssh/sshd_config\n```\n\nChange `PasswordAuthentication` to `no`. You may need to remove the `#` symbol to uncomment the line.\n\n```\nPasswordAuthentication no\n```\n\nChange the `PermitRootLogin` option to `no`.\n\n```\nPermitRootLogin no\n```\n\nRestart the SSH service.\n\n``` bash\n$ sudo service ssh restart\n```\n\nAfter the SSH service restarts, the SSH configuration changes will be applied.\n\n\n##### Change the SSH port\n\nSince all Ubuntu servers have a `root` user and most servers run SSH on port `22` (default), hackers often use automated attacks to guess the `root` password. We already prevented the `root` user from using SSH to login (see above). We can make things more difficult by changing our SSH port to a port other than `22`.\n\n``` bash\n$ sudo nano /etc/ssh/sshd_config\n```\n\nSet the `Port` to a value less than `1024`; e.g., `567`.\n\n```\nPort 567\n```\n\nSave the file and restart the SSH service.\n\n``` bash\n$ sudo service ssh restart\n```\n\nNow, when connecting to our Linode server, we need to specify the SSH port.\n\n``` bash\n$ ssh \u003cyour_username\u003e@myserver.\u003cyour_domain\u003e -p 567\n```\n\n\n#### Fail2Ban\n\n[Fail2Ban][fail2ban] is an application that prevents dictionary attacks on your server. [Fail2Ban][fail2ban] can monitor login attempts across different protocols (SSH, HTTP, SMTP) and will create temporary firewall rules to block traffic from an attacker's IP address. To install,\n\n``` bash\n$ sudo apt-get install fail2ban\n```\n\nTo configure,\n\n``` bash\n$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local\n$ sudo nano /etc/fail2ban/jail.local\n```\n\nIn __both__ the `[ssh]` and `[ssh-ddos]` sections, set the `port` to the SSH port you specified above.\n\n```\n[ssh]\n\nenabled \t= true\nport \t\t= \u003cyour_ssh_port\u003e\n```\n\nIn the `[ssh-ddos]` section, set `enabled` to `true`.\n\n```\n[ssh-ddos]\n\nenabled \t= true\nport \t\t= \u003cyour_ssh_port\u003e\n```\n\nSome additional configuration changes (optional):\n*\tSet the `bantime` option to specify how long a ban should last.\n*\tSet the `maxretry` option to specify the number of allowed retries before an IP is banned.\n\nSave the file and restart Fail2Ban.\n\n``` bash\n$ sudo service fail2ban restart\n```\n\nOnce running, Fail2Ban will block any IP address which exceeds the maximum allowed connection attempts and will log the event to `/var/log/fail2ban.log`.\n\n\n#### Firewall\n\nCreate a firewall to limit and block unwanted inbound traffic. To see the current rules,\n\n``` bash\n$ sudo iptables -L\n```\n\nwhich, beside any rules created by Fail2Ban, should contain an empty ruleset. To create a file for specifying filewall rules,\n\n``` bash\n$ sudo nano /etc/iptables.firewall.rules\n```\n\nPaste the following into the opened file. By default, the rules allow traffic to the following services and ports: HTTP (80), HTTPS (443), SSH (`\u003cyour_ssh_port\u003e`), and ping. Be sure to replace `\u003cyour_ssh_port\u003e` with the port specified in `sshd_config` above.\n\n```\n*filter\n\n#  Allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0\n-A INPUT -i lo -j ACCEPT\n-A INPUT -d 127.0.0.0/8 -j REJECT\n\n#  Accept all established inbound connections\n-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT\n\n#  Allow all outbound traffic - you can modify this to only allow certain traffic\n-A OUTPUT -j ACCEPT\n\n#  Allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL).\n-A INPUT -p tcp --dport 80 -j ACCEPT\n-A INPUT -p tcp --dport 443 -j ACCEPT\n\n#  Allow SSH connections\n#\n#  The -dport number should be the same port number you set in sshd_config\n#\n-A INPUT -p tcp -m state --state NEW --dport \u003cyour_ssh_port\u003e -j ACCEPT\n\n#  Allow ping\n-A INPUT -p icmp --icmp-type echo-request -j ACCEPT\n\n#  Log iptables denied calls\n-A INPUT -m limit --limit 5/min -j LOG --log-prefix \"iptables denied: \" --log-level 7\n\n#  Drop all other inbound - default deny unless explicitly allowed policy\n-A INPUT -j DROP\n-A FORWARD -j DROP\n\nCOMMIT\n```\n\nSave the file and then activate the firewall rules.\n\n``` bash\n$ sudo iptables-restore \u003c /etc/iptables.firewall.rules\n```\n\nVerify the rules:\n\n``` bash\n$ sudo iptables -L\n```\n\nTo ensure that the firewall rules are activated each time your Linode restarts, open\n\n``` bash\n$ sudo nano /etc/network/if-pre-up.d/firewall \n```\n\nand paste\n\n```\n#!/bin/sh\n/sbin/iptables-restore \u003c /etc/iptables.firewall.rules\n```\n\nSave the file and set file permissions.\n\n``` bash\n$ sudo chmod +x /etc/network/if-pre-up.d/firewall\n```\n\n---\n\n## Reverse DNS\n\nWhile DNS allows a domain name to be resolved to an IP address, reverse DNS allows an IP address to be resolved to a domain name. Reverse DNS is useful when network troubleshooting (`ping`, `traceroute`). From the Linode manager, navigate to\n\n```\nLinodes --\u003e Remote Access --\u003e Reverse DNS\n```\n\nand enter your domain.\n\n\n---\n\n## Software\n\n\n#### Compiler \n\nA compiler is often required to install packages and software. To install one,\n\n``` bash\n$ sudo apt-get install build-essential\n```\n\n\n\n#### Git\n\nInstall [git][git]:\n\n``` bash\n$ sudo apt-get install git\n```\n\nOnce installed, configure for use with [GitHub][github-git].\n\n``` bash\n$ git config --global user.name \"\u003cyour_github_username\u003e\"\n$ git config --global user.email \"\u003cyour_github_email\u003e\"\n```\n\nTo interact with GitHub over SSH, first check for any existing SSH keys on your server.\n\n``` bash\n$ ls -al ~/.ssh \n```\n\nIf you see an existing private-public key pair which you can use with GitHub, skip the next step. To generate a new SSH key,\n\n``` bash\n$ ssh-keygen -t rsa -b 4096 -C \"\u003cyour_github_email\u003e\"\n```\n\nAccept the default file name. When prompted, enter a __strong__ passphrase. Once a key is generated, you will see a key fingerprint in your terminal.\n\nTo configure the [ssh-agent][ssh-agent] program to use your SSH key, start the agent in the background\n\n``` bash\n$ eval \"$(ssh-agent -s)\"\n```\n\nand add your SSH key\n\n``` bash\n$ ssh-add ~/.ssh/id_rsa\n```\n\nwhere `\u003cid_rsa\u003e` corresponds to the name of an existing SSH key, if not generated above. Next, copy the public key,\n\n``` bash\n$ cat ~/.ssh/id_rsa.pub\n```\n\nand add to your list of SSH keys on [GitHub][github-ssh-keys]. To verify that everything is working,\n\n``` bash\n$ ssh -T git@github.com\n```\n\nVerify the fingerprint and type `yes`. If the user name matches yours, everything works as expected.\n\n\n\n#### Python\n\nInstall Python environment:\n\n``` bash\n$ sudo apt-get install python-pip python-dev\n$ sudo pip install virtualenv\n```\n\nThe above creates a global `pip` command to install Python packages. You are encouraged __not__ to use it, as packages will be installed globally. Instead, use `virtualenv`.\n\nTo create a new virtual Python environment,\n\n``` bash\n$ virtualenv --distribute \u003cenvironment_name\u003e\n```\n\nwhere `\u003cenvironment_name\u003e` is the name of your choosing; e.g., `python/dev`. To switch to the new environment,\n\n``` bash\n$ cd \u003cenvironment_name\u003e\n$ source bin/activate\n```\n\n`pip` can then be used inside of `virtualenv`.\n\n``` bash\n$ pip search \u003cpackage_name\u003e\n$ pip install \u003cpackage_name\u003e\n```\n\nTo exit a virtual environment,\n\n``` bash\n$ deactivate\n```\n\n\n#### Golang\n\nTo install [Golang][golang-ubuntu], first download a Golang binary\n\n``` bash\n$ sudo wget https://storage.googleapis.com/golang/go$VERSION.$OS-$ARCH.tar.gz\n```\n\nwhere `$VERSION` is your desired version (e.g., `1.5`), `$OS` is your operating system (e.g., `linux`), and `$ARCH` is your architecture (e.g., `amd64`). See the Golang [downloads][golang-downloads] for a list of possible downloads. Next, extract the archive into `/usr/local` \n\n``` bash\n$ sudo tar -C /usr/local -xzf go$VERSION.$OS-$ARCH.tar.gz\n```\n\nFor example,\n\n``` bash\n$ sudo wget https://storage.googleapis.com/golang/go1.5.linux-amd64.tar.gz -P ./downloads\n$ sudo tar -C /usr/local -xzf ./downloads/go1.5.linux-amd64.tar.gz\n```\n\nAdd `/usr/local/go/bin` to the `PATH` environment variable. Open your `~/.profile`\n\n``` bash\n$ sudo nano ~/.profile\n```\n\nand add the following line:\n\n```\nexport PATH=$PATH:/usr/local/go/bin\n```\n\nTo apply the changes to the current shell,\n\n``` bash\n$ source ~/.profile\n```\n\nTo verify that Golang is working,\n\n``` bash\n$ golang version\n```\n\nNext, create a Golang workspace\n\n``` bash\n$ mkdir -p code/go\n```\n\nand update your `~/.profile`\n\n``` bash\n$ sudo nano ~./profile\n```\n\nto include\n\n``` \nexport GOPATH=$HOME/code/go\nexport PATH=$PATH:$GOPATH/bin\n```\n\nReload your `.profile`:\n\n``` bash\n$ source ~/.profile\n```\n\nVerify that everything is working:\n\n``` bash\n$ echo $PATH\n$ echo $GOPATH\n```\n\nNext, let's create a test package.\n\n``` bash\n$ mkdir -p $GOPATH/src/github.com/\u003cyour_github_username\u003e/hello\n$ cd $GOPATH/src/github.com/\u003cyour_github_username\u003e/hello\n$ touch hello.go\n```\n\nOpen the file `./hello.go`\n\n``` bash\n$ nano ./hello.go\n```\n\nand paste\n\n``` \npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Printf(\"Hello, world.\\n\")\n}\n```\n\nSave the file and install the program:\n\n``` bash\n$ go install\n```\n\nTo run the program,\n\n``` bash\n$ hello\n# =\u003e Hello, world.\n```\n\n\n#### Node.js\n\nInstall the [Node version manager][nvm] (NVM):\n\n``` bash\n$ wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash\n```\n\nReload your shell\n\n``` bash\n$ source ~/.profile\n```\n\nand verify that `nvm` is working\n\n``` bash\n$ nvm\n```\n\nTo install the latest version of Node,\n\n``` bash\n$ nvm install v8\n```\n\nCheck the installed Node version:\n\n``` bash\n$ node --version\n```\n\n\n#### Nginx\n\nInstall [Nginx][nginx], a high performance [web server][nginx-wikipedia] with a strong focus on concurrency:\n\n``` bash\n$ sudo apt-get install nginx\n```\n\nTo start [Nginx][nginx],\n\n``` bash\n$ sudo service nginx start\n```\n\nTo configure [Nginx][nginx], first create a backup copy of the default configuration file\n\n``` bash\n$ cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup\n```\n\nNext, copy the template virtual domain configuration file\n\n``` bash\n$ cp /etc/nginx/sites-available/default /etc/nginx/sites-available/\u003cyour_domain\u003e\n```\n\nwhere `\u003cyour_domain\u003e` is the name of your domain; e.g., `example.com`. If you are hosting multiple domains, you should create a virtual domain configuration file for each domain. Once copied, we need to tailor the configuration file(s).\n\n``` bash\n$ sudo nano /etc/nginx/sites-available/\u003cyour_domain\u003e\n```\n\nIn the `server` block, change the `server_name` directive to your domain.\n\n```\nserver_name \u003cmy_domain\u003e;\nserver_name *.\u003cmy_domain\u003e; # process requests for all subdomains\n```\n\nBeneath the `server_name` directive, specify an `access_log` location.\n\n```\n# Absolute path to a directory dedicated to your domain; e.g., /var/www/\u003cyour_domain\u003e/logs/access.log\naccess_log /srv/www/\u003cyour_domain\u003e/logs/access.log;\n```\n\nNext, create `location` directives to match requests with static assets. For example,\n\n```\n # Define routes for static assets:\nlocation / {  \n    # Absolute path to root directory containing static assets:\n    root  /srv/www/\u003cyour_domain\u003e/public;\n\n    # Files to serve if none specified:\n    index index.html index.htm;\n}\n```\n\nIn order for [Nginx][nginx] to __activate__ the virtual host configuration, create a symbolic link between the `sites-available` and `sites-enabled` directories.\n\n``` bash\n$ sudo ln -s /etc/nginx/sites-available/\u003cyour_domain\u003e /etc/nginx/sites-enabled/\u003cyour_domain\u003e\n```\n\nRemove the symbolic link for the `default` configuration file to prevent conflicts.\n\n``` bash\n$ sudo rm /etc/nginx/sites-enabled/default\n```\n\nFinally, reload [Nginx][nginx]\n\n``` bash\n$ sudo service nginx reload\n```\n\nFor more information, see the Linode [guides][linode-nginx].\n\n\n---\n\n## Sites\n\nThe following outlines steps for hosting web assets based on the [Nginx][nginx] configuration above. First, create a directory to store files for all hosted domains.\n\n``` bash\n$ sudo mkdir /srv/www\n```\n\nSet permissions so that all `www` files may be read.\n\n``` bash\n$ sudo chmod 755 /srv/www\n```\n\nFor each domain, create a directory to store site files.\n\n``` bash\n$ sudo mkdir /srv/www/\u003cyour_domain\u003e\n```\n\nCreate a directory to store access logs.\n\n``` bash\n$ sudo mkdir /srv/www/\u003cyour_domain\u003e/logs\n```\n\nNext, grant ownership of each directory to the `user` specified in `nginx.conf`. By default, this `user` is `www-data`.\n\n``` bash\n$ sudo chown -R www-data:www-data /srv/www/\u003cyour_domain\u003e/public\n```\n\nTo test that everything is configured correctly, create an `index.html` file\n\n``` bash\n$ sudo touch /src/www/\u003cyour_domain\u003e/public/index.html\n$ sudo nano /src/www/\u003cyour_domain\u003e/public/index.html\n```\n\nand paste the following content\n\n``` html\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003ctitle\u003eMy Domain\u003c/title\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003ch1\u003eBeep. Boop.\u003c/h1\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nDetermine your `ip address`.\n\n``` bash\n$ ifconfig\n```\n\nOnce determined, enter the `ip address` into your browser and you should see the following:\n\n```\nBeep. Boop.\n```\n\nIf a site is a Git repository, clone the repo into a `www` domain directory\n\n``` bash\n$ cd /srv/www/\u003cyour_domain\u003e\n\n# Assuming an empty directory...\n$ sudo git clone https://github.com/\u003cowner\u003e/\u003crepo\u003e\n```\n\nIf the repository requires build steps, change the directory ownership and permissions. For example,\n\n``` bash\n$ sudo chown -R \u003cuser\u003e ./\u003crepo\u003e/\n\n# Allow a non-root user to read, write, and execute:\n$ sudo chmod -R 775 ./\u003crepo\u003e\n```\n\nSupposing the `\u003crepo\u003e` is a Node.js application, the following should now be possible:\n\n``` bash\n$ cd \u003crepo\u003e\n\n# Use a particular Node version:\n$ nvm use 8\n\n# Install Node dependencies:\n$ npm install\n```\n\n\n---\n\n## References\n\n*\t[Getting started][linode-getting-started]\n*\t[Securing your server][linode-securing-server]\n*\t[Hosting a website][linode-hosting-website]\n*\t[How to setup your linode][how-to-setup-your-linode]\n\n\n\u003c!-- links --\u003e\n\n[linode]: http://linode.com\n[linode-getting-started]: https://www.linode.com/docs/getting-started\n[linode-hosting-website]: https://www.linode.com/docs/websites/hosting-a-website/\n[linode-nginx]: https://www.linode.com/docs/websites/nginx/how-to-configure-nginx\n[linode-securing-server]: https://www.linode.com/docs/security/securing-your-server/\n\n[fail2ban]: https://www.fail2ban.org/wiki/index.php/Main_Page\n\n[git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git\n[github-git]: https://help.github.com/articles/set-up-git/\n[github-ssh-keys]: https://help.github.com/articles/generating-ssh-keys/#platform-linux\n\n[ssh-agent]: https://en.wikipedia.org/wiki/Ssh-agent\n\n[nvm]: https://github.com/creationix/nvm\n\n[nginx]: https://www.nginx.com/\n[nginx-wikipedia]: https://en.wikipedia.org/wiki/Nginx\n\n[golang-ubuntu]: https://github.com/golang/go/wiki/Ubuntu\n[golang-downloads]: https://golang.org/dl/\n\n[how-to-setup-your-linode]: http://feross.org/how-to-setup-your-linode/\n\n\u003c!-- /.links --\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkgryte%2Flinode-setup-notes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkgryte%2Flinode-setup-notes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkgryte%2Flinode-setup-notes/lists"}