Preface
This guide introduces two methods to upload your local blog’s static files (the public folder) to your own server and configure a domain name.
① SFTP - the simplest approach
② Set up a Github repository on your VPS and configure hooks to update local files on the VPS
There’s no clear advantage between these two methods - choose whichever you prefer and feel comfortable with.
What you’ll need: a server (this demo uses Debian/Ubuntu), and a domain name.
SFTP Deployment
Install hexo-deployer-sftp
Install hexo-deployer-sftp. This allows you to deploy your site via SFTP and supports passwordless connections using ssh-agent.
Run the command: npm install hexo-deployer-sftp --save
Modify _config.yml Configuration
Modify the deploy option in your _config.yml file. Here’s a reference template:
deploy:
type: sftp
host: <host>
user: <user>
pass: <password>
remotePath: [remote path]
port: [port]
privateKey: [path/to/privateKey]
passphrase: [passphrase]
agent: [path/to/agent/socket]
| Option | Description | Default |
|---|---|---|
| host | Remote host address | |
| port | Port number | 22 |
| user | Username | |
| pass | Password | |
| privateKey | Path to SSH private key | |
| passphrase | Optional passphrase for private key | |
| agent | Path to ssh socket | $SSH_AUTH_SOCK |
| remotePath | Root directory on remote host | / |
| forceUpload | Overwrite existing files | false |
| concurrency | Maximum number of concurrent SFTP tasks | 100 |
privateKey: If you’ve already generated a certificate locally and uploaded the public key to the .ssh folder, and configured the sshd file to allow key-based login, you can fill in this option. If you set a password, remember to fill in [passphrase]. See the next section for details on generating local keys.
[remote path]: Create a directory on your VPS, for example /var/blog, and enter it here. You can also choose a different directory. The static files from the public folder will be stored here.
Git Deployment
Configure Local SSH Keys
To establish a connection between your local machine and the remote GitHub repository, you need to configure SSH keys locally. This allows you to push code directly to GitHub or remote git repositories. If this is your first time configuring SSH, set up git’s username and email:
$ git config --global user.name "your desired name"
$ git config --global user.email "your desired email"
Then generate your local key: $ ssh-keygen -t rsa -C "the email you just set". If you don’t need to set a password, just press Enter three times. If you do set a password, make sure to remember it.
Afterward, an id_rsa.pub file will appear in your user’s home directory. This is your generated public key, which needs to be uploaded to the .ssh folder later.
Server User Setup
Create a git user: adduser git. You can fill in the password and personal information as you wish.
Switch to the git user, create the ~/.ssh folder and ~/.ssh/authorized_keys file, and assign the appropriate permissions:
su git
mkdir ~/.ssh
vim ~/.ssh/authorized_keys
Press “i” to enter edit mode, copy the public key from the id_rsa.pub file generated locally into authorized_keys, press “esc”, then type “:wq” to save and exit. If you don’t like vim, you can use nano or other editors. The goal is to get the public key in there.
Also, make sure that pubkey authentication is set to yes in the sshd configuration file.
Next, enter the following commands to assign permissions:
chmod 600 /home/git/.ssh/authorized_keys
chmod 700 /home/git/.ssh
Then test whether you can log in to git from your local terminal without a password: ssh -v git@SERVER.
Create Github Repository
Create a repo directory under the var directory as the Git repository directory. Return to the server command line, switch to the root account, and enter: mkdir /var/repo, then assign permissions: chmod -R 755 /var/repo.
Next, create a hexo directory as the website root directory and assign permissions:
mkdir /var/hexo
chown -R git:git /var/hexo
chmod -R 755 /var/hexo
chown -R git:git /var/repo/
chown -R git:git /var/hexo/
Then create a bare git repository:
cd /var/repo
git init --bare hexo.git
We need to create a new Git hook for automatic deployment. In /var/repo/hexo.git, there’s an auto-generated hooks folder. We need to create a new hook file called post-receive inside it. Create the /var/repo/hexo.git/hooks/post-receive file with the following content:
#!/bin/bash
git --work-tree=/var/hexo --git-dir=/var/repo/hexo.git checkout -f
And modify its permissions:
chown -R git:git /var/repo/hexo.git/hooks/post-receive
chmod +x /var/repo/hexo.git/hooks/post-receive
Modify Hexo Configuration
Edit the site configuration file _config.yml, find deploy, and modify it according to this template:
deploy:
type: git
#Change repo to: repo: git@your_ip:/var/repo/hexo.git
repo: git@your_ip:/var/repo/hexo.git
branch: master
Domain Configuration
Caddy
my.domain {
root * /var/hexo
file_server
encode gzip
# Optional: configure logging
log {
output file /var/log/caddy/my.domain.access.log
format common
}
}
Simply replace my.domain with your own domain name and root * /var/hexo with your own directory.
Nginx
server {
listen 80;
listen [::]:80;
server_name my.domain;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name my.domain;
# SSL certificate configuration - replace with actual certificate paths
ssl_certificate /etc/ssl/certs/my.domain.crt;
ssl_certificate_key /etc/ssl/private/my.domain.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_protocols TLSv1.2 TLSv1.3;
root /var/hexo;
index index.html;
access_log /var/log/nginx/my.domain.access.log;
error_log /var/log/nginx/my.domain.error.log;
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location / {
try_files $uri $uri/ =404;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
}
error_page 404 /404.html;
location = /404.html {
internal;
}
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
location ~* \.(log|txt|sql)$ {
deny all;
}
}
Please obtain your own certificate and replace the paths in the SSL certificate configuration section with the absolute paths to your certificates.