Deploying a Go web application on Apache
To deploy a Go web application on Apache, we need to understand how the Go language runs a web app. Go uses the net/http package (standard library) for this, which provides implementations for both HTTP clients and HTTP servers. You can find a good example of its use in the documentation:
running a websitepackage main import ( "io" "log" "net/http" ) func main() { // Hello world, the web server helloHandler := func(w http.ResponseWriter, req *http.Request) { io.WriteString(w, "Hello, world!\n") } http.HandleFunc("/hello", helloHandler) log.Fatal(http.ListenAndServe(":8080", nil)) }
This is an example of the ListenAndServer
method. Then, when we run our web with go run main.go
and go to our browser, we should see “Hello, word” on the screen.
Excellent, we can say that this is our first web page on our local server, and when we run the command go run main.go
we get “Hello, word”.
Here we can see that the server is on port 8080. How could we make Apache implement this?
Apache Configuration
Assuming we already have Apache installed and configured for our website, what should we do to display the content of our Go HTTP Client-Server? There are a few different ways to do this, but the most convenient approach for using Go is to set up a reverse proxy in Apache.
gowebsite.conf<VirtualHost *:80> ServerName tu-dominio.com ProxyPreserveHost On ProxyPass / http://localhost:8888/ ProxyPassReverse / http://localhost:8888/ ErrorLog ${APACHE_LOG_DIR}/mi-app-error.log CustomLog ${APACHE_LOG_DIR}/mi-app-access.log combined </VirtualHost>
Let’s remember that the configuration file will generally need to be in /etc/apache2/sites-available/
So far, everything is good for my application, right? I have my Apache server, and to run the Go server, I run my go run main.go?
The answer to this question is no, we cannot have our console unusable while the server is running.
Creating a Daemon with systemd for My Application
To make our server run in the background, we will need a Daemon or demon, as you may call it. This will need to run the server until we tell it to stop, a simple concept, but it still needs to be configured.
You will need to create a service file, so you will need to do it in /etc/systemd/system/ if you are using Linux Ubuntu.
vim /etc/systemd/system/mygoapp.service/etc/systemd/system/mygoapp.service
[Unit] Description=Mi Aplicación Go After=network.target [Service] ExecStart=/home/tu-usuario/mi-app/mi-app-ejecutable WorkingDirectory=/home/tu-usuario/mi-app Restart=always User=tu-usuario Group=tu-grupo Environment=GIN_MODE=release [Install] WantedBy=multi-user.target
Service config explained
[Unit] – Contains metadata and dependencies about the service being configured.
Description – his is the description of what our service does
After – Indicates that our service will be initialized after these services, in our case after the network service.
[Service]
ExecStart – path to the executable of our application
WorkingDirectory – the directory path to the app
Restart=always – f the application terminates, it will always try to restart.
User – user owner
Group – group owner
Environment – This section allows you to define environment variables that will be available to the service when it runs.
[Install]
WantedBy – Indicates the targets under which this service should be enabled to start automatically when the system boots up.
WantedBy=multi-user.target indicates that the system is in multi-user mode without a graphical environment (console).
Testing the Daemon for Our Go Website on Apache
To all these things works, we have to reload the systemd with the following command:
sudo systemctl daemon-reload
Alright, how do we start and stop the service at will?
Remember, we’re using systemd, so starting and stopping the service will be governed by it.
sudo systemctl stop mygoapp.service
sudo systemctl start mygoapp.service
In case you are using the code directly instead of an executable, the ExecStart value would be different
ExecStart=/usr/local/go/bin/go run main.go