0%

2025

2016年9月第一个博客记录从大三开始实习,到2025年差不多过去10个年头了,毕业工作也快是第7个年头了。从初创公司实习,腾讯、蚂蚁、阿里再到字节。辗转杭州、深圳又回到了广州。经历了17、18年互联网的上升,蚂蚁上市黑天鹅和疫情后的互联网寒冬。10年是一个周期,今年从事业上,储备上也算到了自己的预期,也算是给16年的自己给了一个答卷了。

从去年开始我才会思考自己究竟想过什么样的生活,这个对于我来说是一个很痛苦的过程,又不想陷入工作的怪圈,又不敢大刀阔斧冒进。但回过来看我已经是很幸运了,至少还有选择。不管怎么样,从抱怨生活到热爱生活肯定是没错的。

背景

之前一直有一个细胞自动机链接的项目部署在搬瓦工的服务器上。是原始的ubuntu一步一命令部署,早就已经没法维护。加上搬瓦工的服务器一年需要19.9刀,虽然不贵但是毕竟有免费的Oracle服务器了,就打算把细胞自动机迁移到Oracle的服务器上,顺便docker化掉。

要做什么呢

  • 新建一个dockerfile文件为正式Node项目的启动服务
  • 通过docker-compose.yml组织切分三个启动段:临时Nginx启动服务,证书申请服务,正式Node项目的启动服务。同时准备好两份Nginx文件
  • 在Server端拉取Git源码,通过docker-compose启动细胞自动机的部署

部署代码和流程

源码

部署代码

docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
version: '3'

services:
# 阶段1:临时Web服务(仅用于证书申请)
temp-web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- web-root:/var/www/html
- ./nginx-init.conf:/etc/nginx/nginx.conf
- nginx-cache:/var/cache/nginx
networks:
- app-network
user: "root"
entrypoint: sh -c "mkdir -p /var/cache/nginx && chown -R nginx:nginx /var/cache/nginx && nginx -g 'daemon off;'"
restart: unless-stopped

# 阶段2:证书申请服务
certbot:
image: certbot/certbot
volumes:
- certbot-etc:/etc/letsencrypt
- web-root:/var/www/html
command: certonly --webroot --webroot-path=/var/www/html --email ${your_mail} --non-interactive --agree-tos --no-eff-email -d ${your_domain} --staging
networks:
- app-network

# 阶段3:正式Web服务
web:
build: .
ports:
- "80:80"
- "443:443"
volumes:
- certbot-etc:/etc/letsencrypt
- web-root:/var/www/html
- ./nginx.conf:/etc/nginx/nginx.conf
networks:
- app-network
restart: unless-stopped

volumes:
web-root:
certbot-etc:
certbot-var:
nginx-cache:

networks:
app-network:

dockerfile

这个文件是第三阶段的正式Web服务启动的docker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Dockerfile 优化版
FROM node:14-alpine

# 安装依赖
RUN apk add --no-cache nginx certbot && \
mkdir -p /var/www/html && \
getent group www-data || addgroup -S www-data && \
getent passwd www-data || adduser -S -G www-data -D www-data && \
chown -R www-data:www-data /var/www/html

WORKDIR /app

COPY package*.json ./
RUN npm install && npm install pm2 -g

COPY . .

# 暴露端口
EXPOSE 80 443

# 启动命令
CMD ["sh", "-c", "pm2 start bin/www && nginx -g 'daemon off;'"]

nginx-init.conf

这个是临时的申请证书用的nginx文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
worker_processes auto;

events {
worker_connections 1024;
}

http {
server {
listen 80;
server_name ${your_domain};

location /.well-known/acme-challenge/ {
root /var/www/html;
}

location / {
return 403;
}
}
}

nginx.conf

这个是正式的nginx文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# nginx.conf (更新版)
user www-data;
worker_processes auto;

events {
worker_connections 1024;
}

http {
server {
listen 80;
server_name ${your_domain};

location /.well-known/acme-challenge/ {
root /var/www/html;
}

location / {
return 301 https://$host$request_uri;
}
}

server {
listen 443 ssl;
server_name ${your_domain};

ssl_certificate /etc/letsencrypt/live/${your_domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${your_domain}/privkey.pem;

location / {
proxy_pass http://127.0.0.1:3000; # 这个需要改成本地启动的node服务端口
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
}
}
}

部署流程

启动临时服务

启动临时服务,这个服务是为了给certbot提供域名的path校验,/.well-known/acme-challenge/。这个服务会占用80端口。

1
docker-compose up -d temp-web

certbot证书校验和申请流程

先dry_run一下申请证书的命令,看看证书校验逻辑是否有问题。因为certbot命令加上了--staging命令,所以运行下面的命令并不会实际申请证书,也为了避免测试的时候出发certbot的下发证书限制(7天内只能申请5次证书)链接

1
docker-compose up -d certbot

这里直接启动certbot是因为dry_run执行后查看一下日志是否有问题docker logs ${certbot_container_id}。如果运行没有任何的报错,就可以去掉--staging

停止临时的certbot并且删除临时的certbot

1
2
docker stop ${certbot_container_id}
docker rm ${certbot_container_id}

去除dry_run命令限制

1
sed -i 's/--staging//' docker-compose.yml

去掉--staging再次运行certbot启动命令,就会申请证书的证书。这里采用执行一次就退出的操作,操作会保留volume中的证书。申请好证书后就不要再操作certbot了,特别是不要运行docker-compose down -v操作,会将volume中证书一起删掉。

1
docker-compose run --rm certbot

启动正式服务

首先停止临时服务,防止临时服务一直占用着80端口导致正式服务无法启动

1
docker stop ${temp_web_container_id}

启动正式服务,启动后可以看看${web_container_id}正式服务的日志,看看是否无报错成功拉起正式服务,成功拉起会展示pm2的结果。

1
docker-compose up -d web

证书自动更新流程

部署好之后,需要使用cron创建证书自动更新的逻辑。这样就可以免去手工更新证书的步骤。见工程源代码

1
sh ./scripts/setup_crontab.sh

其他问题记录

发现访问出现(failed)net::ERR_CONTENT_LENGTH_MISMATCH 错误。无法加载js资源文件

解决方案,在nginx中加入proxy_buffering off;

记一次hexo blog的维护

自从21年把自己的blog docker化后就好久没有维护自己的blog了。以前都是一直是没有加入https的自动更新服务的,本次打算加入自动更新certbot的服务。同时都已经进入2025年了让deepseek优化一下自己的dockerfile。

全面升级dockerfile详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 使用 Ubuntu 作为基础镜像
FROM ubuntu:latest

# 设置环境变量(避免交互式提示)
ENV DEBIAN_FRONTEND=noninteractive

# 替换为国内镜像源
RUN sed -i 's#http://deb.debian.org#https://mirrors.163.com#g' /etc/apt/sources.list && \
sed -i 's#http://security.debian.org#https://mirrors.163.com#g' /etc/apt/sources.list && \
rm -rf /var/lib/apt/lists/* && \
apt-get update

# 安装必要的软件
RUN apt-get install -y git openssh-server nginx cron certbot python3-certbot-nginx

# 创建 nginx 用户
RUN useradd -r -s /usr/sbin/nologin nginx

# 初始化 Git 裸仓库(路径保持不变)
RUN git init --bare /root/blogs.git

# 创建目标目录
RUN mkdir -p /var/www/hexo

# 配置 post-receive 钩子
RUN echo "#!/bin/sh" > /root/blogs.git/hooks/post-receive && \
echo "git --work-tree=/var/www/hexo --git-dir=/root/blogs.git checkout -f" >> /root/blogs.git/hooks/post-receive && \
chmod +x /root/blogs.git/hooks/post-receive

# 初始化仓库并创建初始提交(解决 bad object 问题)
RUN git clone /root/blogs.git /tmp/blogs && \
cd /tmp/blogs && \
echo "Initial commit" > README.md && \
git add README.md && \
git config --global user.email "you@example.com" && \
git config --global user.name "Your Name" && \
git commit -m "Initial commit" && \
git push origin master && \
cd / && \
rm -rf /tmp/blogs

# 配置 SSH 服务(仅生成主机密钥,不限制登录形式)
RUN rm -f /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_ecdsa_key /etc/ssh/ssh_host_ed25519_key && \
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && \
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" && \
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""

# 添加 Nginx 配置文件
ADD nginx/hexo.conf /etc/nginx/nginx.conf

# 暴露端口
EXPOSE 22
EXPOSE 80
EXPOSE 443

# 启动 SSH 和 Nginx 服务
CMD service ssh start && nginx -g "daemon off;"
  1. 将nginx镜像升级成ubuntu的镜像,安装openssh-server nginx cron certbot python3-certbot-nginx必要的服务。后续通过命令启动nginx服务
  2. ubuntu新增nginx用户才能操作nginx启动,和nginx.conf匹配
  3. 一键化certbot设置,新增DEBIAN_FRONTEND=noninteractive无交互配置,让certbot可以自动执行。但和之前一样,证书和docker分离,还是docker run好后,要自己去docker内部申请一下证书。
  4. 修复之前配置ssh的的一些公钥不合理的dockerfile命令。
  5. 在初始化仓库后,提交一个节点避免仓库创建后没有提交记录导致bad object问题。

github地址
dockerhub地址

使用步骤

前期步骤

docker安装看这里(这里拿ubuntu举例子):安装docker

docker设置自己的用户权限

1
2
3
sudo usermod -aG docker $USER

newgrp docker

docker登录自己的dockerhub

1
docker login -u ${yourhub_username}

拉取自己的dockerhub,具体可以按照上面我提供的github自己写一份自己的

1
docker pull ${yourhub}/${yourdocker}:latest

运行docker

volume自己的证书目录,开放80和443端口和8004的blog更新端口

1
docker run -v $(pwd)/letsencrypt:/etc/letsencrypt -d -p 80:80 -p 443:443 -p 8004:22 ${yourhub}/${yourdocker}:latest

进入启动后的docker内部

1
docker exec -it ${your_docker_id} /bin/bash

在运行起来的docker实例内部创建证书,创建证书更新脚本

申请证书

1
certbot --nginx -d "[your_domain.com]"

配置ssh,让本地的Blog可以推送过来

记得要改[your_ssh_public_key]为你自己的public_key

1
mkdir ~/.ssh
1
echo "[your_ssh_public_key]" > ~/.ssh/authorized_keys
1
chmod 600 ~/.ssh/authorized_keys
1
chmod 700 ~/.ssh
1
mkdir /run/sshd
1
/usr/sbin/sshd

配置自动更新certbot

在docker容器内部执行以下命令

1
echo "0 0 1 * * /usr/bin/certbot renew --quiet" >> /etc/crontabs/root

如果说没有/etc/crontabs/文件夹,那么创建/etc/crontabs/ 文件夹

1
mkdir -p /etc/crontabs

hexo推送

这个看我《Hexo博客部署的终极解决办法》这个的章节就好

记录一些其他问题

因为早早就把macbook换成了arm64架构的m1芯片了。所以docker本地build的时候会有些问题。需要做以下构建命令的替换

1
2
3
4
5
docker build -t ${docker_name} . 

# 替换成下面命令,上面不要用了,要用moby/buildkit buildx做一个垫片,不然就会构建arm64的产物而不是远程服务器的linux/amd64产物

docker buildx build --load --platform linux/amd64 -t ${docker_name} .

推送dockerhub的时候要打tag不然没有userscope推送不上去

1
docker tag ${docker_name}:latest ${userscope}/${docker_name}:latest

docker在本地构建老拉不下镜像需要开启bash或者zsh自己的http代理

(这个就没有教程了,科学上网)

一直发现hexo deploy的时候没有办法push上去,提示! [remote rejected] HEAD -> master (missing necessary objects)或者error: cannot create async thread: Operation not permitted或者fatal: bad object错误。

其实就是远端的docker太老了,更新一下远端服务器的docker版本。

某些环境(例如 GitLab 16.0 或 CircleCI 环境)报告需要 Docker 20.10.10 或更高版本才能正常运行。如果你使用的 Docker 版本较低,建议升级 Docker。相关问题

Oracle的服务器可以通过一些占用脚本提高服务器的使用率避免回收。

链接

记得在root下执行。首次使用root要通过sudo passwd 新建密码

前言

背景

17年在大学用Hexo部署了第一个博客后,一直对Hexo个人博客进行改造升级。最开始是挂载在Github.io,后用Nginx迁移至自有域名chanchun.net,在后来启用了GitHooks让Hexo构建产物直接SSH推送至云,再后来通过letsencrypt 升级了Https。自从Oracle Cloud开放了免费实例后,一直想把博客服务迁移到免费的云上(无奈工作太忙,也怪搬瓦工服务器太难用)。那么与其从0开始迁移,还不如把一直以来的沉淀(Https、GitHooks、Nginx)也一起Docker化掉。方便以后继续迁移,也给自己想折腾博客的人一个我认为最终极的解决方案。

你需要准备什么

云基础配置

  • 买一个Niubility的域名(推荐国外域名注册商)
  • 买一个Niubility云服务实例(推荐国外云服务商)
  • 把你的域名DNS解析至你的云公网IP(生效时间预计从0-48小时不等)

Hexo游刃有余

  • 熟悉Hexo的基本操作,熟悉hexo init hexo new hexo clean hexo generate hexo server hexo deploy 等命令,并能启动Hexo服务构建出静态html,如果已经搭建过了简单的博客系统就更棒棒

Docker

  • 了解一下Docker基本操作docker build docker run 等等一系列操作

正题

思路

第一步,新建一个hexo-docker工程来构建Docker镜像(基于Nginx镜像),里面有且仅包含Dockerfile和初始Nginx配置。Dockerfile中描述了Githooks挂载地址,安装好了Certbot命令,并加入初始Nginx配置。

第二步,在云服务中直接Docker Run起构造好的镜像,进入镜像生成好letsencrypt证书,配置好远程SSH提供给Hexo Deploy。

第三步,配置好本地的Hexo代码,Hexo Deploy就能看到带绿锁的自有域名的博客了。

Show Code

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#基于Nginx镜像
FROM nginx:latest

#换国内的源,这里用网易源
RUN sed -i 's#http://deb.debian.org#https://mirrors.163.com#g' /etc/apt/sources.list
RUN sed -i 's#http://security.debian.org#https://mirrors.163.com#g' /etc/apt/sources.list

#更新Docker中的apt-get
RUN rm -Rf /var/lib/apt/lists/* && apt-get update

#安装Git,挂载Githooks钩子,并将产物放置在var/www/hexo中
RUN apt-get install -y git
RUN git init --bare ~/blogs.git
RUN mkdir -p /var/www/hexo
RUN echo "git --work-tree=/var/www/hexo --git-dir=/root/blogs.git checkout -f" >~/blogs.git/hooks/post-receive
RUN chmod a+x ~/blogs.git/hooks/post-receive

#SSH初始化
RUN apt-get install -y openssh-server
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -y
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -y
RUN ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -y

#安装Certbot
RUN apt-get install -y certbot
RUN apt-get install -y python3-certbot-nginx

#初始化Nginx配置挂载,这里选择直接覆盖所有配置
ADD nginx/hexo.conf /etc/nginx/nginx.conf

#暴露22 SSH
#暴露80 HTTP
#暴露443 HTTPS
EXPOSE 22
EXPOSE 80
EXPOSE 443

Nginx配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
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;
server {
listen 80;
server_name chanchun.net; #记得改成自己的域名

location / {
root /var/www/hexo; #要和刚刚的Githooks目录对应上
index index.html index.htm;
}

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

我已经将代码上传到了Github,给个星星?

构建和启动

构建

1
docker build -t hexo-docker .

启动

这里要在云上Run了,如果在本机跑的化能跑起来但是没法继续搞证书了。至于怎么把构建好的镜像转移到云上呢?各位搞开源的Docker Hub也行,直接Copy也行。

注意这里使用了volume方案,为后续申请证书的挂载做准备

1
docker run -v $(pwd)/letsencrypt:/etc/letsencrypt -d -p 80:80 -p 443:443 -p 8004:22 hexo-docker

我已经将构建出的Docker镜像上传到了Docker Hub,给个星星?

配置证书

进入Docker Container

1
docker exec -it "[your_container_name]" /bin/bash

申请证书

我们在用Dockfile来构建的时候已经安装了Certbot,我们可以利用Certbot帮忙安装Https证书,同时Certbot会自动识别上文中配置的Nginx文件,加入证书验证和443端口开放。

1
certbot --nginx -d "[your_domain.com]"

这里就按照提示一步一步走就是了,最后见到congratulation!就能证明证书已经安装好了,因为我们在docker run 时采用了volume方案,生成出的证书会挂载到云服务的$(pwd)/letsencrypt目录下,并关联到Docker内部的/etc/letsencrypt目录 。这样能保证镜像中不带CA证书,解耦的同时也确保Docker在迁移的时候的安全性。

可以看到/etc/nginx/nginx.conf 已经加入了443端口和证书路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
server_name chanchun.net;

location / {
root /var/www/hexo;
index index.html index.htm;
}

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

listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/chanchun.net/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/chanchun.net/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

证书更新

1
/usr/bin/certbot renew

Letsencrypt 3个月就需要更新一次,很多人用自动更新任务来完成更新。我这边就不想用了,因为我觉得每个月收到提示邮件后上云更新一把是一件很愉快的事。如果你需要自动更新可以使用下面命令

1
echo "0 0 1 * * /usr/bin/certbot renew --quiet" >> /etc/crontabs/root

配置Hexo Deploy的SSH

还是在Docker镜像内操作,不需要离开Docker镜像内部。如果离开了看上述“进入Docker Container”命令。

依次执行下面的命令吧,注意your_ssh_public_key改成自己电脑上的公钥,在~/.ssh/xxx.pub 中。

1
mkdir ~/.ssh
1
echo "[your_ssh_public_key]" > ~/.ssh/authorized_keys
1
chmod 600 ~/.ssh/authorized_keys
1
chmod 700 ~/.ssh
1
mkdir /run/sshd
1
/usr/sbin/sshd

Hexo推送

恭喜你胜利在即,到这一步已经可以退出Docker镜像,并且退出云服务器了(有没有发现完全没改云服务器本身的配置,感叹Docker实在强大!)。接下来都是直接在本机操作。

更改Hexo _config.yml 配置

1
2
3
4
5
deploy:
type: git
repo: root@hexo-test:/root/blogs.git #Docker中8004端口作为SSH端口,但repo没法写端口号,写一个hexo-test作为config
branch: master

新增~/.ssh/config文件

~/.ssh/config中配置你的云服务公网ip,ssh端口即可(按照文章来就是8004)

1
2
3
Host hexo-test
HostName [your_remote_server_ip]
Port 8004

推送Hexo

1
hexo deploy

Success! 当hexo deploy 成功之后,你的博客就可以通过域名访问了,并且带有小绿锁哦。

chanchun.net

总结一下

这套方案有三解耦:云服务和Docker解耦,证书(在云服务上)和Docker解耦,HTML静态资源和Docker解耦(Githooks)。同时Nginx也无需手工配置。这套方案不仅可用于博客,只要是静态文件的部署,都能适用。

最后求个赞吧:GithubDocker Hub

使用Proxychains给你的Shell加上代理

Proxychains是啥?

他是一个命令行预加载器,用于挂钩动态链接程序中的套接字,并通过一个或多个socks / http代理重定向它。

GitHub地址 链接

MacOS和Linux系本身通过Shadowsocks代理之后,通过PAC名单可以识别出要代理的域名。但要求代理应用必须支持Sock5,如果不支持,那么也没有办法通过Shadowsocks代理。我们的Shell控制台环境是不支持Sock代理的,只支持HTTP代理。如果我们不在终端设置 http_proxy 代理,那么我们的Shell控制台是无法通过Shadowsocks代理的。

附 终端设置 http_proxy 代理方法

其实如果不嫌麻烦,我们可以通过在终端设置http_proxy来将Sock代理换成HTTP代理。这样Shell环境也可以曲线救国而使用Shadowsocks代理啦。

1
2
export http_proxy='http://localhost:8888'
export https_proxy='http://localhost:8888'

取消代理

1
2
unset http_proxy
unset https_proxy

如果有兴趣也可以将这个命令放在.bashrc或者.zshrc中,让我们的Shell控制台全局代理启动更加方便一些。

首先你的有自己的小飞机(Mac)

通过Proxychains代理的首先你的有自己的Shadowsocks。这里推荐搭建Shadowsocks-R环境(SSR),因为SSR比普通的Shadowsocks增加了协议和混淆,稳定性更高。

ShadowsocksX-NG 下载这个ShadowsocksX-NG,输入你的SSR配置即可。首先保证你的浏览器能够被ShadowsocksX-NG代理,因为浏览器是默认支持Sock协议的。

如果你是Linux系,你可以借助sslocal命令开启自己的Shadowsocks,具体的参数就不在此文中详细介绍

使用Proxychains4

安装(Mac)

1
brew install proxychains-ng

安装完成之后你将有proxychains4命令

安装(Linux)

1
2
3
4
git clone https://github.com/rofl0r/proxychains-ng.git
cd proxychains-ng
./configure
make && make install

配置参数

修改/usr/local/etc/proxychains.conf 中的配置(Mac brew安装)

注意:Linux系不会默认生成conf文件,需要将上工程中./src/proxychains.conf 里面的配置Copy到目录中

如果proxychain4命令不手动制定配置文件路径,它会自动寻找配置。

1
2
3
4
5
6
[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
# socks4 127.0.0.1 9050
socks5 127.0.0.1 1086 # 这里设置自己的代理地址和端口

这就可以了么?

proxychains4配置生效之后,我们在终端使用proxychains4 加上命令就可以在终端代理了。但是这真的可以代理了么???答案是MacOS不行,而Linux系的同学已经OK了。

测试测试:

1
proxychains4 curl ip.cn

结果:

1
当前 IP:42.120.102.128 来自:浙江省杭州市 阿里云

修改苹果SIP(System Integrity Protection)设置

如果是Linux系的 此时你应该成功代理了 忽略下文

macOS 10.11后,苹果加入SIP设置就会导致部分命令是执行不成功的,就包括使用socks的proxychains4。如果我们要解决这个问题,我们就要关掉SIP。

  • 重启Mac,按下Command+R直到出现Apple Logo。
  • 选择实用工具->终端
  • 输入命令csrutil disable。出现类似于“成功禁用SIP”的意思就表示成功了。

如果还要打开SIP,最后的步骤csrutil enable即可

测试关闭SIP之后的Proxychains4

测试测试:

1
proxychains4 curl ip.cn

结果:

1
当前 IP:42.3.27.177 来自:香港特别行政区 香港电讯

如果看到的ip是境外的ip,这样即可成功在命令行中通过proxychains4代理啦。此时如果关掉proxychains4。

测试测试:

1
curl ip.cn

结果:

1
当前 IP:42.120.102.128 来自:浙江省杭州市 阿里云

升级你的hexo为https

本文以Debian 8为服务器栗子

最近升级了个人博客为https协议,写一个详细的教程帮助更多人升级https。

https的详细原理在此文中省略,简略来说,既是客户端在访问服务器时需要一个数字证书(里面包括公钥),它由权威机构(CA, Certificate Authority)颁发,来确认公钥确实是服务器发出来的。

证书价格不菲,大概7天需要几美金到几百美金不等(根据认证的等级和域名覆盖范围区分),所以很多证书都是商业级的,提供给商业网站使用。

获取免费证书

那么个人将无法获取数字证书么?不是的,为了鼓励https的普及,EFF成立了免费证书最大的提供商为Let’s Encrypt,可以提供免费证书。那么小型的网站,就可以使用免费证书升级为https啦。

当然Let’s Encrypt生成的证书,只能是单域名的,而且只有最低级的域名验证。

克隆letsencrypt客户端

1
$ git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

如果遇到权限问题,记得先创建/opt/letsencrypt文件夹再,更改文件夹权限为可写入。

注册证书

Nginx指向静态路径注册证书

注册一个域名证书非常简单,使用letsencrypt就能生成https所需的证书。当然,用letsencrypt生成的证书只支持域名验证,只需要用letsenctypt的自动注册证书命令,证明这个域名是自己的是用的即可。

1
2
$ cd /opt/letsencrypt
$ ./letsencrypt-auto certonly -a webroot --webroot-path=/var/www/me -d me.chanchun.net # 可以使用多个 -d 添加多个域名

letsencrypt可以帮我们自动注册证书,--webroot-path是静态资源所指的路径。-d是域名域名,也可以多个-d增加多个域名。最后确保使用https的域名都被letsencrypt注册。

后续将会让你继续输入邮箱信息

如果出现Congratulations!字样,则证明证书已被自动注册。

Nginx转发型注册证书

如果是使用Nginx直接重定向服务器本地服务,非静态资源,就省略--webroot-path-a参数。

1
2
$ cd /opt/letsencrypt
$ ./letsencrypt-auto certonly -d ca.chanchun.net

输入命令之后

1
2
3
4
5
6
7
How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Nginx Web Server plugin (nginx)
2: Spin up a temporary webserver (standalone)
3: Place files in webroot directory (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-3] then [enter] (press 'c' to cancel):

选择1即可,后续将会让你继续输入邮箱信息

如果出现Congratulations!字样,则证明证书已被自动注册。

Nginx配置

直到这一步,证书已经就绪,只要配置好Nginx即可完美升级https。Nginx安装、启动教程请具体请教Nginx教程。

转发到本地服务Nginx配置Sample:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#http重定向到https配置 证书验证配置
server {
listen 80;
server_name ca.chanchun.net; # 这里写你的域名
location ^~ /.well-known/acme-challenge/ { # 不要修改 letsencrypt需要验证你的域名
default_type "text/plain";
proxy_pass http://localhost:3000; # 填写你需要转发的服务器地址
}
location = /.well-known/acme-challenge/ { # 不要修改 letsencrypt需要验证你的域名
return 404;
}
return 301 https://$server_name$request_uri;
}

# https配置
server {
# SSL Configuration
listen 443 ssl;
server_name ca.chanchun.net; # 这里写你的域名

# copy from https://cipherli.st
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off; # Requires nginx >= 1.5.9
ssl_stapling on; # Requires nginx >= 1.3.7
ssl_stapling_verify on; # Requires nginx => 1.3.7
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

# specify cert files
ssl_certificate /etc/letsencrypt/live/ca.chanchun.net/fullchain.pem; # 中间填写你的域名
ssl_certificate_key /etc/letsencrypt/live/ca.chanchun.net/privkey.pem; # 中间填写你的域名
location / {
proxy_pass http://localhost:3000; # 填写你需要转发的服务器地址
}
}

指向静态文件Nginx配置Sample:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
server {
listen 80;
server_name me.chanchun.net; # 这里写你的域名
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/me; # 这里写你的静态文件目录
}
location = /.well-known/acme-challenge/ {
return 404;
}
return 301 https://$server_name$request_uri;
}

server {
# SSL Configuration
listen 443 ssl;
server_name me.chanchun.net; # 这里写你的域名
# specify cert files
ssl_certificate /etc/letsencrypt/live/me.chanchun.net/fullchain.pem; # 中间写你的域名
ssl_certificate_key /etc/letsencrypt/live/me.chanchun.net/privkey.pem; # 中间写你的域名
location / {
root /var/www/me; # 这里写你的静态文件目录
index index.html index.htm; # 这里写你暴露的静态文件
}
}

Nginx配置各有各的配置方法,这里只要保证四点:

  • 域名配置正确
  • 静态文件目录路径、本地服务目录路径配置正确
  • .well-known/acme-challenge目录配置正确
  • 要保证80默认端口和443ssl端口都有配置

如果配置好Nginx,那么访问网站就会有绿色的小钥匙啦,说明你的https站点搭建好。

自动更新证书

letsencrypt证书最多只有90天,90天之后我们需要重新注册证书,当然这个可以交给服务器自己做啦。

验证自己的证书是否可以更新

1
2
$ cd /opt/letsencrypt
$ ./letsencrypt-auto renew --dry-run

此命令只是验证 不会更新证书

如果出现Congratulations!字样或者已经更新字样则证明可以自动更新。如果出现错误,或者说路径找不到的情况,大多数情况是.well-known/acme-challenge目录配置没有正确的配置成功

编写crontab脚本

1
$ crontab -e

脚本内容

1
30 2 * * 1 /opt/letsencrypt/letsencrypt-auto renew >> /var/log/le-renew.log

如果遇到权限问题,可先创建/var/log目录再设置其权限为可写入

成功

享受https的绿色小锁吧!

前后端分离开发跨域实践

跨域这个问题可谓是老生常谈,在实际工程开发中也有不同的解决办法。本篇文章来总结跨域的原理和我在前后端完全分离开发中,遇到跨域的解决方法。

跨域的原理

跨域条件

跨域是浏览器限制,目的是为了防止不同域之间访问造成安全问题。何为不同域呢?简单理解,既是不同域名下则产生了跨域。详细包括不同的端口、不同协议、不同子域名、不同域名下都算跨域。具体可以见下面的引用表格:

URL 说明 是否跨域
http://www.a.com/a.js, http://www.a.com/b.js 同一域名下
http://www.a.com/lab/a.js, http://www.a.com/script/b.js 同一域名下不同文件夹
http://www.a.com:8000/a.js, http://www.a.com/b.js 同一域名,不同端口
http://www.a.com/a.js, https://www.a.com/b.js 同一域名,不同协议
http://www.a.com/a.js, http://192.22.45.12/b.js 域名和域名解析ip
http://www.a.com/a.js, http://script.a.com/b.js 两个子域名不相同
http://www.a.com/a.js, http://a.com/b.js 主域名和子域名 是(cookie也无法访问)
http://www.cnblogs.com/a.js, http://www.a.com/b.js 不同域名

由于跨域浏览器的限制,所有来源于一个域内的Js请求在请求其他域时,就会被浏览器拦截下。注意这里的拦截下是指在请求回调过程中。

跨域资源共享(Cross-Origin Resource Sharing,简称 CORS)

既然是跨域是浏览器事件,那么浏览器进行跨域资源共享呢。就要利用CORS机制,跨域资源共享标准新增了一组 HTTP 首部字段:

  • 请求头:

Origin 参数表示发起一个针对跨域资源共享的请求的来源

  • 响应头:

Access-Control-Allow-Origin 表示指定哪一类网站可以跨域资源共享

Access-Control-Allow-Methods 表示服务器允许客户端使用POST, GET 和 OPTIONS 方法发起请求

Access-Control-Expose-Headers 头让服务器把允许浏览器访问的头放入白名单

Access-Control-Max-Age 头指定了preflight请求的结果能够被缓存多久

Access-Control-Allow-Credentials 头指定了当浏览器的credentials设置为true时是否允许浏览器读取response的内容

Access-Control-Allow-Headers 首部字段用于预检请求的响应,其指明了实际请求中允许携带的首部字段

当产生跨域时,就可以通过配置HTTP头部字段来防止请求被浏览器拦截的情况。具体只要在服务器的响应中,设置响应头Access-Control-Allow-Origin和请求头Origin匹配,即可通过CORS机制避免跨域问题。也可以通过设置Access-Control-Allow-Origin为*,表示服务器允许来自所有域的请求。

实际问题

Cookie与Session

在许多业务场景中,往往会存在用户登录态需求,这是通过传统的Session来实现的,而对于Session的客户端记录,大部分的B/S架构会存在于Cookie中,通过Cookie中的SessionID来保留客户端Session记录。

在正常的非跨域请求中,Cookie是可以带入请求头的,那么SessionID会隐藏的通过请求带给服务器,服务器通过SessionID判断是否是保持Session会话的客户端。然而在跨域请求中,即使设置了CORS,请求可以相互通信,但是Cookie还是无法通过请求带给服务端,此时Session会话无法保持。

通过尝试将Access-Control-Allow-Credentials设置为True即可将Cookie带入请求。并且在客户端中要将withCredentials参数设置为true。匹配之后才能传递Cookie。

具体在xhr对象中是以withCredentials参数存在,在fetch中是以credentials: ‘include’;参数存在。同时后台的Access-Control-Allow-Credentials设置也要根据不同的后台框架的HTTP头设置进行调整匹配。

推荐CORS插件

cc-inviewport模块

这个小模块能判断HTMLElement是否在视窗内

关键代码

1
2
3
4
5
const mainOffsetTop = element.offsetTop //元素到顶部距离
const mainHeight = element.offsetHeight //元素高度
const winHeight = window.innerHeight //视窗大小
const winScrollTop = window.document.body.scrollTop + window.document.documentElement.scrollTop //已经卷过的距离
return !(winScrollTop > mainOffsetTop + mainHeight + offset || winScrollTop + offset < mainOffsetTop - winHeight) //返回是否在视窗内的布尔值

目前兼容移动端和主流浏览器,如果有改进欢迎MR

使用方法

Npm直接安装

1
2
3
4

const inviewport = require('cc-inviewport');

inviewport(HTMLElement);

或者使用build中的源代码

1
2

cc_inviewport(HTMLElement);

cc_inviewport挂载在Window下

源码地址:源码

喜欢给个Star,欢迎贡献改进

腾讯实习记事

大致

4月拿到腾讯的实习offer,从7月初到10月底在腾讯实习了4个月。

岗位:IOS开发工程师(从前端转过来)

部门:CDG国际业务部(IBG)

工作

负责VOOV客户端的学习和开发。团队是采取快速迭代开发,基本上每两三周完成一个小版本(约4到5次小迭代)。整体的节奏还是小步快跑,快速实现需求。

VOOV介绍

VOOV是一个面向海外的直播App,目前在香港、马来、印尼、泰国、南非等国家以及地区上线。

完成的需求(时间顺序)

  • 随机UITableViewController
  • 短视频搜索
  • 增加VOOV链接和更多分享渠道
  • 多人视频分享、邀请、以及私信
  • 直播间测速

学习总结

  • 成熟团队开发流程。对比学校或者是年轻团队,腾讯更多带来的是一种规范。调研分析->需求评审->产品提单->交互UI->编码(客户端、Web、接入层和后台快速迭代)->测试(回归)->运维(上线)->Local本地团队动态配置->上报(数据分析)。切身体会到项目管理展现出来的执行力。除此之外,也能体会各个团队之间的合作,沟通。
  • 项目架构。大前端时代,很多东西其实是相通的,在设计模式上,VOOV使用MVVM,分离ViewModel和LogicModel,使Logic层和UI层分离,再通过UI层Handler和Logic层Server链接。这些概念其实在前端领域例如Vue中也有体现。
  • 可持续性?代码统一命名规范,目录结构,Wiki,注释,稳定性,代码可读性,协议规范。
  • 直播技术。直播端RTMP推流,OBS,CMS配置系统,房间功能,帧率码率,弱网络下逻辑。
  • 国际化。翻译、多语言样式设计,多国的Local团队合作。

想说的话

  • 成就感。当自己做的需求交付Apple审核再上线给百万用户使用时,还是有一份成就感。这就是大公司给平凡的程序员的最大魅力。
  • 学习。在项目中学习,在项目中成长是最快的。刚来IBG的时候真的只是一个只看过两个星期Object-C的IOS小白,在VOOV中留下自己的脚印,这是四个月前我想都不敢想的。这是在VOOV项目组最宝贵的进步和收获。
  • 方法。
    • 一定要带着问题去找答案,有一个想法自己尝试去做,做出来了之后再对比吸收尝试别人的方案。
    • 学会给多的时间去深挖,不要仅仅局限于API层级的东西。
  • 娄子。哈哈在实习中差点没少捅娄子,把提测代码给git revert掉。还试过给翻译提3份错误代码。
  • 感谢。感谢导师 Justin 和组长 Grayson还有帮助过我的所有终端组童鞋们。

最后

送给腾讯那段努力的岁月。

最近在干嘛?

已经是大三下学期了5月份了,终于有时间清闲下来写写东西了。

从暑假1月中到现在,找实习已经3个多月了,也紧张了三个多月。最终尘埃落定最终暑假实习去腾讯CDG做Web前端或者移动端的开发。

可能之后就开始准备实习的东西了,熟悉腾讯CDG实习的技术栈,同时完成自己之前计划的学习路线。

春招的总结将会在下一篇的博文中推出。也请期待吧。