sourcegraph / sourcegraph-public-snapshot

Code AI platform with Code Search & Cody
https://sourcegraph.com
Other
10.11k stars 1.28k forks source link

Improve Nginx and Let's Encrypt documentation #2475

Open KattMingMing opened 5 years ago

KattMingMing commented 5 years ago

I went through the Nginx and Let's Encrypt documentation and ran into several issues. Below is documentation on the steps I followed to configure Nginx with a self signed cert and using cert bot.

Deploying on GCP and accessing your instance

  1. Install Sourcegraph with Docker on Google Cloud
  2. Navigate to Compute Engine and click VM instances
  3. SSH into VM
    • Click the SSH button from the Compute Engine VM instances page
  4. Navigate to the Sourcegraph directory.
    • sudo su;
    • cd /root/.sourcegraph

Create admin account

Navigate to the External IP address of the VM. You may need to wait a few minutes for it to be accessible.

  1. Create an admin account
  2. Navigate to /site-admin
  3. Copy the management configuration password and save it somewhere safe

Update DNS Records

There can be a delay when updating DNS records, so I did this step earlier than expected.

  1. In a separate tab, navigate to your registrar
  2. Create custom resource record by following your registrar's instructions
    1. Create an A record
      • Map the domain name to the External IP address of the VM
      • 1m TTL so the cache is updated immediately, the default is typically 1hr.

Setting up SSL / TLS

There are a few ways to configure SSL / TLS.

Option A: Self signed certificate

Generate the certificate

Inside the VM run the following commands:

  1. sudo su;

  2. cd /root/.sourcegraph/config

  3. If you don't already have a TLS certificate and key, you can generate them with the following command. Note: Replace sourcegraph.example.com with your domain.

    openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout \
    ~/.sourcegraph/config/sourcegraph.example.com.key -out \
    ~/.sourcegraph/config/sourcegraph.example.com.crt
Update nginx.conf

Update the nginx.conf that is in the same directory. Replace sourcegraph.example.com with your domain.

The three lines in the nginx.conf need to be updated with your domain:

        server_name sourcegraph.example.com;
        ssl_certificate YOUR_CERTIFICATE.crt;
        ssl_certificate_key YOUR_KEY.key;
error_log stderr;
pid /var/run/nginx.pid;
events{
}
http {
    server_tokens off;
# We can upload large extensions
    client_max_body_size 150M;
# Don't timeout websockets quickly. Default is 60s. This is the timeout
# between reads/writes, not the full session timeout.
    proxy_send_timeout 1h;
    proxy_read_timeout 1h;
    access_log off;
    upstream backend {
        server localhost:8080;
    }
    server {
        listen 7080;
        return 301 https://$host:7433$request_uri;
    }
    server {
        listen 7443 ssl;
        server_name sourcegraph.example.com;
        ssl_certificate YOUR_CERTIFICATE.crt;
        ssl_certificate_key YOUR_KEY.key;
# use low age for testing
        add_header Strict-Transport-Security "max-age=10" always;
        location / {
            proxy_pass http://backend;
            proxy_set_header Host $http_host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}
Restart container

Since we do not have access to the command line of the NGINX container directly, we cannot use the nginx command to control NGINX. Fortunately, Docker provides kill command for sending signals to the container.

  1. Get the Sourcegraph container ID
    • docker ps | grep sourcegraph | awk '{print $1}'
  2. docker rm -f <container ID>
  3. docker run -d --publish 80:7080 --publish 443:7443 --publish 2633:2633 --restart unless-stopped --volume /root/.sourcegraph/config:/etc/sourcegraph --volume /root/.sourcegraph/data:/var/opt/sourcegraph sourcegraph/server:3.1.1

Your instance should now be accessible with a self signed certificate.

Option B: Let's Encrypt

Let’s Encrypt automatically provisions TLS certificates so that your server is accessible via HTTPS.

To do this, I followed the Using Let’s Encrypt with nginx on Ubuntu 16.04 instructions.

Let's Encrypt needs to access port 80 which is currently in use by Sourcegraph, so it was necessary to stop the container. Inside the VM run the following commands:

  1. docker ps | grep sourcegraph | awk '{print $1}'
  2. docker rm -f <container ID>

Next, I needed to install certbot.

  1. sudo su;
  2. According to certbot documentation:
    apt-get update
    apt-get install software-properties-common
    add-apt-repository universe
    add-apt-repository ppa:certbot/certbot
    apt-get update
    apt-get install certbot python-certbot-nginx 
  3. Create the certificate using certonly
    • sudo certbot --nginx certonly
  4. Once created copy the certificates into the Sourcegraph directory
    • cp /etc/letsencrypt/live/$YOUR_DOMAIN/fullchain.pem /etc/letsencrypt/live/$YOUR_DOMAIN/privkey.pem /root/.sourcegraph/config
  5. Stop the nginx service that was started by certbot
    • service nginx stop
  6. Modify your nginx.conf
Update nginx.conf with certbot

The three lines in the nginx.conf need to be updated with your domain.

By default fullchain.pem and privkey.pem are names generated by certbot.

        server_name sourcegraph.example.com;
        ssl_certificate fullchain.pem;
        ssl_certificate_key privkey.pem;
error_log stderr;
pid /var/run/nginx.pid;
events{
}
http {
    server_tokens off;
# We can upload large extensions
    client_max_body_size 150M;
# Don't timeout websockets quickly. Default is 60s. This is the timeout
# between reads/writes, not the full session timeout.
    proxy_send_timeout 1h;
    proxy_read_timeout 1h;
    access_log off;
    upstream backend {
        server localhost:8080;
    }
    server {
        listen 7080;
        return 301 https://$host:7433$request_uri;
    }
    server {
        listen 7443 ssl;
        server_name sourcegraph.example.com;
        ssl_certificate fullchain.pem;
        ssl_certificate_key privkey.pem;
# use low age for testing
        add_header Strict-Transport-Security "max-age=10" always;
        location / {
            proxy_pass http://backend;
            proxy_set_header Host $http_host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}
  1. docker run -d --publish 80:7080 --publish 443:7443 --publish 2633:2633 --restart unless-stopped --volume /root/.sourcegraph/config:/etc/sourcegraph --volume /root/.sourcegraph/data:/var/opt/sourcegraph sourcegraph/server:3.1.1

Now your instance should be accessible via HTTPS with your signed certificate generated by certbot.

KattMingMing commented 5 years ago

I realized that there's a way to avoid shutting down the nginx service when going through the certbot steps. After Step 4:

Once created copy the certificates into the Sourcegraph directory

  • cp /etc/letsencrypt/live/$YOUR_DOMAIN/fullchain.pem /etc/letsencrypt/live/$YOUR_DOMAIN/privkey.pem /root/.sourcegraph/config

Certbot will be running on port 80 (as designed) user's can run a slightly modified docker run command to avoid shutting down the nginx service (omit --publish 80:7080)

1. docker run -d --publish 443:7443 --publish 2633:2633 --restart unless-stopped --volume /root/.sourcegraph/config:/etc/sourcegraph --volume /root/.sourcegraph/data:/var/opt/sourcegraph sourcegraph/server:3.1.1

I'm not 100% if that's the best way to do this.. User's would still need to perform a restart of the sourcegraph/server docker container after renewing certificates.

It looks like the default expiration is 3 months so if there's a better way to handle this we should document that as well. cc/ @keegancsmith any feedback on the above issue and this possible improvement would be appreciated.

ryan-blunden commented 5 years ago

I've added how to create a self-signed cert that can be validated by browsers - https://docs.sourcegraph.com/admin/ssl_https_self_signed_cert_nginx

Next up is Let's Encrypt docs