Xubuntu + Nginx + Go(+ Pion/WebRTC) + Node.js
Tags: ubuntu, nginx, go
Published: 2022-08-14 15:56:09

## Intro
I will try creating a development environment with Xubuntu, Nginx, and Go.

### Environments
* Xubuntu ver.22.04
* Nginx ver.1.22.0
* Go ver.go1.19 linux/amd64
* Node.js ver.18.7.0

## Xubuntu
First, I change the directory names to English.

```
LANG=C xdg-user-dirs-gtk-update
```

* [Ubuntu でホームディレクトリ内のディレクトリ名を英語表記に - 雑廉堂の雑記帳](https://www.rough-and-cheap.jp/linux/ubuntu-change-xdg-directory-name/)

After that, I install some applications.

### Installed by apt
* vim
* git
* gimp
* curl

### Install packages
* Google Chrome
* Visual Studio Code

## Installing Go and Node.js
### Go
I can download and install Go by following the installation guide.

* [Download and install - The Go Programming Language](https://go.dev/doc/install)

To add "/usr/local/go/bin" to the PATH environment variable, I execute this command.

```
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
source ~/.bashrc
```

After installing, I clone [my Go project](https://github.com/masanori840816/webappsample).

### Node.js
To use TypeScript, Webpack, and etc., I install Node.js using NodeSource according to the Node.js documentation.

* [Installing Node.js via package manager - Node.js](https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions)
* [NodeSource Node.js Binary Distributions - GitHub](https://github.com/nodesource/distributions)

## Nginx
### Installing
I install Nginx according to the documentation.

* [nginx: Linux packages](https://nginx.org/en/linux_packages.html#Ubuntu)

### Serving Go projects
From what I have found in some blog posts and documents on the internet, it seems that Nginx uses Reverse Proxy to serve Go projects.
And because I want to access the WebRTC sample page from some PCs and smart phones what are connected by local network, I have to serve it over htttps.

### Reverse Proxy
To use reverse proxy, I can edit Nginx config files.

Normally, I can write them in "/etc/nginx/nginx.conf", but for Port:80, I must write in "/etc/nginx/conf.d/default.conf".

#### default.conf
```conf
server {
    listen       80;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    # When clients access "http://localhost/webrtc", Nginx redirect to "http://localhost:8080"
    location /webrtc {
        proxy_pass http://localhost:8080;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
```

### https
To serve pages over htttps, I need to create and configure a certificate.
This time, it is only for development, I create locally-trusted development certificates with mkcert.

* [mkcert - FiloSottile - GitHub](https://github.com/FiloSottile/mkcert)
* [mkcert.org](https://mkcert.org/)

I install the pre-built binaries according to the README.

After executing "mkcert -install", I can create certification and key files.

```
mkcert -key-file local_key.pem -cert-file local_cert.pem 192.168.XX.YYY
```

"192.168.XX.YYY" represents the IP address of my machine.

I saved them on my home directory(/home/example) this time.

After that, I update "/etc/nginx/nginx.conf".

#### nginx.conf
```conf
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

   sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;

#when clients access "https://192.168.XX.YYY:443/webrtc",
#the server will serve "webappsample".
server {
    listen 443 ssl;
    server_name 192.168.XX.YYY;
    ssl_certificate /home/example/local_cert.pem;
    ssl_certificate_key /home/example/local_key.pem;
    location /webrtc {
        proxy_pass http://localhost:8080;
    }
  }
}
```

### Serve my WebRTC project(webappsample)
To serve my WebRTC project, I have to update it.

#### Paths
Because the page is served with reverse proxy, its URL will be changed.

#### index.html
```html
<!DOCTYPE html>
<html>
    <head>
        <title>WebRTC Sample</title>
        <meta charset="utf-8">
        <link href="{{.}}/css/site.css" rel="stylesheet" />
    </head>
    <body>
...
        <script src="{{.}}/js/main.page.js"></script>
        <script>Page.init('{{.}}');</script>
    </body>
</html>
```

#### main.go
```go
...
func main() {
	hub := *newSSEHub()
	go hub.run()

	http.Handle("/webrtc/css/", http.StripPrefix("/webrtc", http.FileServer(http.Dir("templates"))))
	http.Handle("/webrtc/js/", http.StripPrefix("/webrtc", http.FileServer(http.Dir("templates"))))
	http.HandleFunc("/webrtc/sse/message", func(w http.ResponseWriter, r *http.Request) {
		sendSSEMessage(w, r, &hub)
	})
	http.HandleFunc("/webrtc/sse/", func(w http.ResponseWriter, r *http.Request) {
		registerSSEClient(w, r, &hub)
	})

	http.Handle("/", &templateHandler{filename: "index.html", serverUrl: "https://192.168.XX.YYY:443/webrtc"})
	log.Fatal(http.ListenAndServe("localhost:8080", nil))
}
```

#### Server Sent Events(SSE)
Although I can access the page and Media Streams, I still can't connect with WebRTC.
Because when I tried connecting with Server Sent Events, I would get 301(Moved Permanently).

To avoid this, I have to add more properties into nginx.conf.

#### nginx.conf
```conf
...
server {
    listen 443 ssl;
    server_name 192.168.XX.YYY;
    proxy_buffering off;
    proxy_cache off;
    proxy_set_header Connection '';
    proxy_http_version 1.1;
    chunked_transfer_encoding off;
    ssl_certificate /home/example/local_cert.pem;
    ssl_certificate_key /home/example/local_key.pem;
    location /webrtc {
        proxy_pass http://localhost:8080;
    }
  }
}

```
#### Resources

* [nginx documentation](https://nginx.org/en/docs/)
* [Beginner’s Guide - nginx](https://nginx.org/en/docs/beginners_guide.html)
* [NGINX Cookbook, 2nd Edition](https://www.oreilly.com/library/view/nginx-cookbook-2nd/9781098126230/)
* [EventSource / Server-Sent Events through Nginx - StackOverflow](https://stackoverflow.com/questions/13672743/eventsource-server-sent-events-through-nginx)
* [Why do I need to use http.StripPrefix to access my static files? - StackOverflow](https://stackoverflow.com/questions/27945310/why-do-i-need-to-use-http-stripprefix-to-access-my-static-files)