作者: Jet L

  • 【HIFI】弗西音频FOSI AUDIO SK02拆解及 I²C 上电数据

    1、拆解及部分细节

    如图所示,板子还是比较简洁规整的:

    • DAC采用单颗ESS 的 ES9038Q2M
    • 运放部分四颗SGM 8262,测量±V引脚,工作电压差为15.8V左右(板子上标却是±6V),工作发热量巨大,为运放供电的是一颗 SGM6623 4.4A 微型升压转换器。
    • 运放之后还有两颗模拟开关,在B站关于该厂ZD3的视频下看到有人讨论了同款芯片作用,也是来自SGM的芯片——SGM3710(不过官网已经找不到这颗芯片的PDF,只有第三方来源)。
    • USB音频控制器采用SAVITECH的SA9312,可以安装BRAVO-HD驱动,实现ASIO输出。
    • 单片机使用STC的8H1K28
    • 音量旋钮旁边还有一颗TI的LM358放大器。
    • 主板看起来是四层PCB,似乎做了数字、模拟部分的隔离设计,主板与外壳接地的弹性触点焊接歪的离谱,是有什么神秘设计么XD

    2、监听I²C得到上电逻辑

    利用逻辑分析仪,分析上电后的通讯:

    3、SK02对ES9038Q2M的寄存器操作(GPT分析):

    注:该部分通过GPT分析,感觉近期GPT不是很好用,总是出错,我对着手册复核了一部分,仅供参考:

    寄存器操作数据 (hex)说明
    64读取0x72Chip ID=0x1C,automute_status=1(自动静音触发),lock_status=0(DPLL未锁定)
    8写入0x99GPIO 配置:gpio2_cfg=9 (Analog Input Shutdown),gpio1_cfg=9 (Analog Input Shutdown)
    12写入0xFFASRC/DPLL 带宽:dpll_bw_serial=15,高带宽;dpll_bw_dsd=15,高带宽
    14写入0x8ASoft Start 配置:soft_start=1(正常启动),soft_start_on_lock=0(解锁时不自动升压),soft_start_time=10
    22写入0x30THD Compensation C2 高字节=0x30(16-bit signed coefficient 高位)
    23写入0x00THD Compensation C2 低字节=0x00(16-bit signed coefficient 低位)
    24写入0x80THD Compensation C3 高字节=0x80(16-bit signed coefficient 高位)
    25写入0x01THD Compensation C3 低字节=0x01(16-bit signed coefficient 低位)
    64读取0x72Chip ID=0x1C,automute_status=1,lock_status=0(重复读取确认)
    8写入0x99GPIO 配置再次设置:gpio2_cfg=9,gpio1_cfg=9(保持 Analog Input Shutdown)
    12写入0xFFASRC/DPLL 带宽再次设置:dpll_bw_serial=15,高带宽;dpll_bw_dsd=15,高带宽
    14写入0x8ASoft Start 配置再次设置:soft_start=1,soft_start_on_lock=0,soft_start_time=10
    22写入0x30THD Compensation C2 高字节=0x30
    23写入0x00THD Compensation C2 低字节=0x00
    24写入0x80THD Compensation C3 高字节=0x80
    25写入0x01THD Compensation C3 低字节=0x01
    1写入0x84Input Selection:serial_length=32-bit,serial_mode=I2S,auto_select=DSD/Serial自动选择,input_select=serial
    8写入0x88GPIO 配置更新:gpio2_cfg=8 (Standard Input),gpio1_cfg=8 (Standard Input)
    15写入0x5CVolume Control 1=0x5C (-40dB)
    16写入0x5CVolume Control 2=0x5C (-40dB)
    7写入0x80Filter & Mute:filter_shape=apodizing fast roll-off,bypass_osf=0(使用内部滤波器),mute=0(未静音)
    7读取0x80读取寄存器 7:确认滤波器配置和静音状态
    7写入0x80Filter & Mute 重写:filter_shape=apodizing fast roll-off,bypass_osf=0,mute=0
    7读取0x80再次读取寄存器 7:确认滤波器配置和静音状态

    上电后的完整原始数据:

    6653126-6653410 I2C: Address/data: Address write: 48
    6653073-6653073 I2C: Address/data: Start
    6653410-6653451 I2C: Address/data: Write
    6653451-6653492 I2C: Address/data: ACK
    6653493-6653818 I2C: Address/data: Data write: 40
    6653818-6653859 I2C: Address/data: ACK
    6653856-6653856 I2C: Address/data: Start repeat
    6653909-6654193 I2C: Address/data: Address read: 48
    6654193-6654233 I2C: Address/data: Read
    6654234-6654274 I2C: Address/data: ACK
    6654262-6654477 I2C: Address/data: Data read: 72
    6654491-6654518 I2C: Address/data: NACK
    6654527-6654527 I2C: Address/data: Stop
    6654564-6654564 I2C: Address/data: Start
    6654617-6654901 I2C: Address/data: Address write: 48
    6654901-6654941 I2C: Address/data: Write
    6654942-6654982 I2C: Address/data: ACK
    6654984-6655308 I2C: Address/data: Data write: 08
    6655309-6655349 I2C: Address/data: ACK
    6655358-6655682 I2C: Address/data: Data write: 99
    6655683-6655723 I2C: Address/data: ACK
    6655723-6655723 I2C: Address/data: Stop
    6656014-6656014 I2C: Address/data: Start
    6656068-6656352 I2C: Address/data: Address write: 48
    6656352-6656393 I2C: Address/data: Write
    6656393-6656434 I2C: Address/data: ACK
    6656435-6656760 I2C: Address/data: Data write: 0C
    6656760-6656801 I2C: Address/data: ACK
    6656809-6657134 I2C: Address/data: Data write: FF
    6657134-6657175 I2C: Address/data: ACK
    6657174-6657174 I2C: Address/data: Stop
    6657411-6657411 I2C: Address/data: Start
    6657465-6657749 I2C: Address/data: Address write: 48
    6657749-6657790 I2C: Address/data: Write
    6657790-6657831 I2C: Address/data: ACK
    6657831-6658157 I2C: Address/data: Data write: 0E
    6658156-6658197 I2C: Address/data: ACK
    6658205-6658531 I2C: Address/data: Data write: 8A
    6658530-6658571 I2C: Address/data: ACK
    6658571-6658571 I2C: Address/data: Stop
    6658808-6658808 I2C: Address/data: Start
    6658862-6659146 I2C: Address/data: Address write: 48
    6659146-6659187 I2C: Address/data: Write
    6659186-6659227 I2C: Address/data: ACK
    6659228-6659554 I2C: Address/data: Data write: 16
    6659553-6659594 I2C: Address/data: ACK
    6659602-6660036 I2C: Address/data: Data write: 30
    6659981-6660076 I2C: Address/data: ACK
    6660022-6660022 I2C: Address/data: Stop
    6660259-6660259 I2C: Address/data: Start
    6660312-6660597 I2C: Address/data: Address write: 48
    6660597-6660638 I2C: Address/data: Write
    6660637-6660678 I2C: Address/data: ACK
    6660679-6661005 I2C: Address/data: Data write: 17
    6661004-6661045 I2C: Address/data: ACK
    6661053-6661379 I2C: Address/data: Data write: 00
    6661378-6661419 I2C: Address/data: ACK
    6661419-6661419 I2C: Address/data: Stop
    6661656-6661656 I2C: Address/data: Start
    6661709-6661994 I2C: Address/data: Address write: 48
    6661994-6662035 I2C: Address/data: Write
    6662034-6662075 I2C: Address/data: ACK
    6662076-6662402 I2C: Address/data: Data write: 18
    6662401-6662442 I2C: Address/data: ACK
    6662450-6662776 I2C: Address/data: Data write: 80
    6662775-6662816 I2C: Address/data: ACK
    6662816-6662816 I2C: Address/data: Stop
    6663053-6663053 I2C: Address/data: Start
    6663106-6663391 I2C: Address/data: Address write: 48
    6663391-6663432 I2C: Address/data: Write
    6663431-6663472 I2C: Address/data: ACK
    6663473-6663799 I2C: Address/data: Data write: 19
    6663798-6663839 I2C: Address/data: ACK
    6663903-6664229 I2C: Address/data: Data write: 01
    6664228-6664269 I2C: Address/data: ACK
    6664269-6664269 I2C: Address/data: Stop
    6665462-6665462 I2C: Address/data: Start
    6665515-6665799 I2C: Address/data: Address write: 48
    6665799-6665839 I2C: Address/data: Write
    6665840-6665880 I2C: Address/data: ACK
    6665882-6666207 I2C: Address/data: Data write: 40
    6666207-6666248 I2C: Address/data: ACK
    6666245-6666245 I2C: Address/data: Start repeat
    6666298-6666582 I2C: Address/data: Address read: 48
    6666582-6666622 I2C: Address/data: Read
    6666623-6666663 I2C: Address/data: ACK
    6666651-6666866 I2C: Address/data: Data read: 72
    6666880-6666907 I2C: Address/data: NACK
    6666916-6666916 I2C: Address/data: Stop
    6666953-6666953 I2C: Address/data: Start
    6667006-6667291 I2C: Address/data: Address write: 48
    6667291-6667332 I2C: Address/data: Write
    6667331-6667372 I2C: Address/data: ACK
    6667373-6667697 I2C: Address/data: Data write: 08
    6667698-6667738 I2C: Address/data: ACK
    6667747-6668125 I2C: Address/data: Data write: 99
    6668126-6668166 I2C: Address/data: ACK
    6668166-6668166 I2C: Address/data: Stop
    6668404-6668404 I2C: Address/data: Start
    6668457-6668742 I2C: Address/data: Address write: 48
    6668742-6668783 I2C: Address/data: Write
    6668782-6668823 I2C: Address/data: ACK
    6668824-6669150 I2C: Address/data: Data write: 0C
    6669149-6669190 I2C: Address/data: ACK
    6669198-6669524 I2C: Address/data: Data write: FF
    6669523-6669564 I2C: Address/data: ACK
    6669564-6669564 I2C: Address/data: Stop
    6669801-6669801 I2C: Address/data: Start
    6669855-6670139 I2C: Address/data: Address write: 48
    6670139-6670180 I2C: Address/data: Write
    6670180-6670221 I2C: Address/data: ACK
    6670221-6670547 I2C: Address/data: Data write: 0E
    6670547-6670588 I2C: Address/data: ACK
    6670596-6670921 I2C: Address/data: Data write: 8A
    6670921-6670962 I2C: Address/data: ACK
    6670961-6670961 I2C: Address/data: Stop
    6671198-6671198 I2C: Address/data: Start
    6671252-6671536 I2C: Address/data: Address write: 48
    6671536-6671577 I2C: Address/data: Write
    6671577-6671618 I2C: Address/data: ACK
    6671619-6671998 I2C: Address/data: Data write: 16
    6671998-6672039 I2C: Address/data: ACK
    6672047-6672372 I2C: Address/data: Data write: 30
    6672372-6672413 I2C: Address/data: ACK
    6672412-6672412 I2C: Address/data: Stop
    6672649-6672649 I2C: Address/data: Start
    6672703-6672987 I2C: Address/data: Address write: 48
    6672987-6673027 I2C: Address/data: Write
    6673028-6673068 I2C: Address/data: ACK
    6673070-6673394 I2C: Address/data: Data write: 17
    6673395-6673435 I2C: Address/data: ACK
    6673444-6673768 I2C: Address/data: Data write: 00
    6673769-6673809 I2C: Address/data: ACK
    6673810-6673810 I2C: Address/data: Stop
    6674047-6674047 I2C: Address/data: Start
    6674100-6674385 I2C: Address/data: Address write: 48
    6674385-6674426 I2C: Address/data: Write
    6674426-6674467 I2C: Address/data: ACK
    6674467-6674793 I2C: Address/data: Data write: 18
    6674792-6674833 I2C: Address/data: ACK
    6674842-6675167 I2C: Address/data: Data write: 80
    6675167-6675208 I2C: Address/data: ACK
    6675207-6675207 I2C: Address/data: Stop
    6675444-6675444 I2C: Address/data: Start
    6675498-6675836 I2C: Address/data: Address write: 48
    6675836-6675931 I2C: Address/data: Write
    6675877-6675972 I2C: Address/data: ACK
    6675919-6676244 I2C: Address/data: Data write: 19
    6676244-6676285 I2C: Address/data: ACK
    6676293-6676618 I2C: Address/data: Data write: 01
    6676618-6676659 I2C: Address/data: ACK
    6676658-6676658 I2C: Address/data: Stop
    6677101-6677101 I2C: Address/data: Start
    6677154-6677439 I2C: Address/data: Address write: 48
    6677439-6677480 I2C: Address/data: Write
    6677479-6677520 I2C: Address/data: ACK
    6677521-6677847 I2C: Address/data: Data write: 01
    6677846-6677887 I2C: Address/data: ACK
    6677895-6678221 I2C: Address/data: Data write: 84
    6678220-6678261 I2C: Address/data: ACK
    6678261-6678261 I2C: Address/data: Stop
    6678291-6678291 I2C: Address/data: Start
    6678345-6678629 I2C: Address/data: Address write: 48
    6678629-6678670 I2C: Address/data: Write
    6678670-6678711 I2C: Address/data: ACK
    6678712-6679037 I2C: Address/data: Data write: 08
    6679037-6679078 I2C: Address/data: ACK
    6679086-6679411 I2C: Address/data: Data write: 88
    6679411-6679452 I2C: Address/data: ACK
    6679451-6679451 I2C: Address/data: Stop
    6679686-6679686 I2C: Address/data: Start
    6679739-6680078 I2C: Address/data: Address write: 48
    6680078-6680119 I2C: Address/data: Write
    6680118-6680159 I2C: Address/data: ACK
    6680160-6680486 I2C: Address/data: Data write: 0F
    6680485-6680526 I2C: Address/data: ACK
    6680534-6680860 I2C: Address/data: Data write: 5C
    6680859-6680900 I2C: Address/data: ACK
    6680900-6680900 I2C: Address/data: Stop
    6680930-6680930 I2C: Address/data: Start
    6680983-6681268 I2C: Address/data: Address write: 48
    6681268-6681309 I2C: Address/data: Write
    6681308-6681349 I2C: Address/data: ACK
    6681350-6681674 I2C: Address/data: Data write: 10
    6681675-6681715 I2C: Address/data: ACK
    6681724-6682050 I2C: Address/data: Data write: 5C
    6682049-6682090 I2C: Address/data: ACK
    6682090-6682090 I2C: Address/data: Stop
    12626945-12626945 I2C: Address/data: Start
    12626998-12627283 I2C: Address/data: Address write: 48
    12627283-12627324 I2C: Address/data: Write
    12627323-12627364 I2C: Address/data: ACK
    12627365-12627689 I2C: Address/data: Data write: 07
    12627690-12627730 I2C: Address/data: ACK
    12627728-12627728 I2C: Address/data: Start repeat
    12627781-12628066 I2C: Address/data: Address read: 48
    12628066-12628107 I2C: Address/data: Read
    12628106-12628147 I2C: Address/data: ACK
    12628134-12628350 I2C: Address/data: Data read: 80
    12628364-12628391 I2C: Address/data: NACK
    12628400-12628400 I2C: Address/data: Stop
    12628434-12628434 I2C: Address/data: Start
    12628487-12628771 I2C: Address/data: Address write: 48
    12628771-12628811 I2C: Address/data: Write
    12628812-12628852 I2C: Address/data: ACK
    12628854-12629178 I2C: Address/data: Data write: 07
    12629179-12629219 I2C: Address/data: ACK
    12629228-12629552 I2C: Address/data: Data write: 80
    12629553-12629593 I2C: Address/data: ACK
    12629594-12629594 I2C: Address/data: Stop

    4、单片机检测选项

    单片机型号: STC8H1K28
    软件协议, V3.0: 7.3.13U

    当前芯片的硬件选项为:
    . 系统ISP工作频率: 23.938MHz
    . 内部IRC振荡器的频率: 11.054MHz
    . 掉电唤醒定时器的频率: 34.825KHz
    . 振荡器放大增益使能
    . 用户EEPROM大小被设置为 0.5 K
    . P3.2和P3.3与下次下载无关
    . 上电复位时增加额外的复位延时
    . 复位引脚用作普通I/O口
    . 检测到低压时复位
    . 低压检测门槛电压 : 2.00 V
    . 上电复位时,硬件不启动内部看门狗
    . 上电自动启动内部看门狗时的预分频数为 : 256
    . 空闲状态时看门狗定时器停止计数
    . 下次下载用户程序时,将用户EEPROM区一并擦除
    . 下次下载用户程序时,没有相关的端口控制485
    . 下次下载时不需要校验下载口令
    . 内部参考电压: 1184 mV (参考范围: 1100~1300mV)

  • 【音频】TASCAM DR-701D如何正确回放立体声

    TASCAM DR-701D录音机,作为一款多通道线性录音机,其设计上并不适合作为一款回放设备使用,但是如果你真的,真的很想用只支持WAV,还不能完整显示文件名字符的它来放音乐,真的很想用它内部的古老的罗姆BA4580RF+TPA4411运放来回放音乐,那也不是不能放,虽然和DR100MK3一样底噪感人。

    那么我们会遇到第一个问题,其默认输出的音频是被MIX过的,没有任何分离度可言,这对于音频回放过于灾难了,那么如何解决这个问题呢?

    方法很简单——进入菜单第二页,将混音器的CH1/CH2的MS设置为录制,即可得到正确的立体声回放。

    此刻回放音乐你甚至还能额外获得两颗0电平指示灯,非常的复古,非常的美味。

  • 【音频】神牛VDS-M3枪式麦克风拆解

    神牛VDS-M3指向性麦克风,关于此麦克风的资料很少,官方初始定价似乎是千元,现在普遍二百左右,不确定用料是否有过改动,该拆解只对应目前200左右的产品。

    主要的能找到参数的芯片已经标记在图中,核心采用 一颗 14mm 咪头,电池为一颗 18490,运放为ADI LT6234(似乎是主板上最贵的芯片),DFN 8封装, 周边还留了个额外焊盘。高低切、增益切换开关应该是通过三颗SN74LVC1G3157DBVR。

    该麦克风的功能和造型类似罗德的NTG4 +,不过可惜网上基本没有NTG 4+的拆解资料,唯一一篇拆解在eeworld 论坛,不过拆的那款怎么看都是个山寨款。

    但是,有意思的就在这里,那款寨版NTG 4+使用的运放和模拟开关方案和神牛这款一毛一样,隔离变压器都长得一样,区别在供电和微处理器部分,可能用的类似方案🤣,不过神牛这个主板做工看起来好一些。

    另外,拆解此类麦克风注意不要硬拽底部xlr座,拆卸所有螺丝后要从上往下把主体推出来,否则可能会把xlr连接线拽断,还得重新焊接(就是我)。

    以上仅供参考。

  • 【音频】TASCAM DR100MK3 的音频架构及改造

    早些年我购入了一个DR100MK3录音笔,看中其又能录音又能回放,相当于大号的录音机+MP3。

    不过回放功能在用几次后感觉并不如人意,其底噪较大,声音较为拥挤,所以后续基本没有再使用。

    后来看了一些“发烧”贴,想当然想去换一下机内的运放,想能不能提升一些效果,当然结果可想而知,没有考虑配套电路+压根没有练习过的焊功,想当然的操作自然是差点把主板搞废了。

    几年过去了,机子还是那个机子,知识越学越多,越学越感觉自己无知,在多次学习电烙铁的使用后,最终还是成功在录音机的主板上修补了七个SOP8的焊盘,让几年前搞坏的录音机重获新生,在此期间,寻找了一些手册,发现了一些有趣的事情。

    1、DR100MK3的运放是OPA1652吗?

    OPA1652是用于麦克风的前置放大,并不是用于音频输出【经过了拆机验证】。

    2、DR100MK3的音频回放架构是?

    两颗AK4558同时作为DAC,其中一颗AK4558+NJM4580C用于Line Out输出,一颗AK4558+NJM4580C经过音量调节,通过一颗BD5461GUL放大输出到机内喇叭,耳机输出则是在音量调节后,经过一颗TPA4411再输出到耳机口。【经过了拆机验证】

    在这个架构下,经过简单的RMAA测试,音频回放在15kHz后就快速滚降,只更换运放可以拓展频率响应的范围,比如我将NJM4580C更换为了OPA1612,其他电路不做调整,测得频响在20kHz后滚降,不过响应曲线没有之前那么平直,在5kHz至15kHz之间有略微波动,噪音及动态范围的总体指标均略有上升,幅度不大。

    NJM4580C下的FR图:

    NJM4580C下的RMAA测试结果(EXT-LINE IN 2 LINE OUT):

    Frequency response (from 40 Hz to 15 kHz), dB+0.07, -0.57Good
    Noise level, dB (A)-97.4Excellent
    Dynamic range, dB (A)98.0Excellent
    THD, %0.00081Excellent
    THD + Noise, dB (A)-88.3Good
    IMD + Noise, %0.00618Excellent
    Stereo crosstalk, dB-67.9Good
    IMD at 10 kHz, %0.00533Excellent
    General performanceVery good

    OPA1612下的FR图:

    更换OPA1612后的RMAA测试结果(EXT-LINE IN 2 LINE OUT):

    Frequency response (from 40 Hz to 15 kHz), dB+0.07, -0.09Very good
    Noise level, dB (A)-100.7Excellent
    Dynamic range, dB (A)102.3Excellent
    THD, %0.00070Excellent
    THD + Noise, dB (A)-89.9Good
    IMD + Noise, %0.00527Excellent
    Stereo crosstalk, dB-74.0Good
    IMD at 10 kHz, %0.00442Excellent
    General performanceVery good

    综合测试结果,硬素质还是距离专业播放器有不少差距。由于缺乏测试设备,其回放音乐的效果无法准确量化,不再推测。

    3、DR100MK3的麦克风大小和型号是?

    DR100MK3内置四颗麦克风【从架构图及BOM表中获得】,均为Primo的产品,其中两颗指向性麦克风——EM164(φ10.0mm x 4.5mm)【也可能是EM182,这里网上能获取到的BOM表和架构图有冲突。另外EM164的规格表显示最大声压级是120,EM182则是132】,两颗为全向麦克风——EM281(φ5.8mm x 2mm)。【这颗全向麦克风规格表最大声压级128,DR100MK3的宣传页显示125,鉴于广告宣传的一般原理,如果DR100MK3选择了EM182,那么他们一定会宣传其高达132的声压级,但是没有,因此量产机的指向性麦克风大概率为EM164】

  • 【网站】Nginx[warn]错误: an upstream response is buffered to a temporary file xxx while reading upstream的解决方法

    如果采用的Nginx+Apache,请求会通过proxy到Apache。

    例如:

        location / {
            proxy_pass http://127.0.0.1:8080;
            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 https;
            proxy_redirect off;
        }

    这就存在一个问题,也是导致服务器几次宕机的问题,在遇到突发的大频率请求下,尤其是对一些大图、视频之类的体积较大的文件进行请求,Nginx会写入、读取大量的缓存,出现类似的错误,导致硬盘IO暴涨,进而让低配置服务器卡死。

    在Nginx的错误日志中就表现为大量的an upstream response is buffered to a temporary file XXX while reading upstream之类的日志,观察发现基本都是较大的视频、图片、JS文件等。

    解决方法:

    1、可以在Nginx.conf配置适当的缓存,启用proxy buffer(不写on似乎也是默认启用的),然后观察是否依旧存在类似的问题。

    2、如果有大文件例如视频之类静态文件,可以将其进行静态处理,直接由Nginx进行处理,避免频繁的IO读写。

    官方文档:https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffers

    proxy_buffering on;
    proxy_buffer_size 16k;
    proxy_buffers 16 32k;
    proxy_busy_buffers_size 256k;
    proxy_temp_file_write_size 256k;

    在站点的Nginx配置中对静态文件进行单独处理,要指定网站的目录位置。

    参考WordPress相关设置:https://developer.wordpress.org/advanced-administration/server/web-server/nginx/

    root /var/html/wp; #定义网站根目录
        location ~ /\. {
        deny all;#拒绝访问隐藏文件
        }
        location ~* /(?:uploads|files)/.*\.php$ {
        deny all;#拒绝uploads、filrs文件夹的php执行
        }
        location = /favicon.ico {
        log_not_found off;#网站图标文件不记录日志
        access_log off;
        }
        location = /robots.txt {
        allow all;#允许robots文件访问
        log_not_found off;
        access_log off;
        }
        location ~* \.(?:jpg|jpeg|png|gif|webp|ico|css|js|woff2?|ttf|svg|eot|mp4|webm|mov|mp3)$ {
            access_log off;#对静态资源做nginx处理
            expires 30d;
            add_header Cache-Control "public";
            try_files $uri =404;
        }
       location / {#其他请求转发到apache
        proxy_pass http://127.0.0.1:8080;
        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-Host $server_name;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off;
        }
  • 【网站】为SSL证书自动续期设定正确的Nginx配置

    使用certbot进行renew证书操作,基于Nginx+Apache。

    在webroot模式下的Nginx配置,需要对80端口和443端口进行配置,以保证验证程序可以读取/.well-known/acme-challenge/路径

    
    # 80端口
     # ACME challenge
        location ^~ /.well-known/acme-challenge/ {
            root  #webroot路径;
            allow all;
        }
       # 其他请求跳转 HTTPS
        location / {
            return 301 https://example.cn$request_uri;
        }
    
    
    # 443端口
    # ACME challenge
        location ^~ /.well-known/acme-challenge/ {
            root #webroot路径;
            allow all;
        }
    
  • 【网站】为WordPress配置正确的文件夹权限

    参考链接

    Hardening WordPress – Advanced Administration Handbook | Developer.WordPress.org

    # 切换到WP目录
    cd /var/www/wordpress
    
    # 将所有权设置为 www-data(用户和组)
    sudo chown -R www-data:www-data .
    
    # 所有目录设为 755
    sudo find . -type d -exec chmod 755 {} \;
    
    # 所有文件设为 644
    sudo find . -type f -exec chmod 644 {} \;
    
    # 强化 wp-config.php 权限
    sudo chmod 640 wp-config.php
    
  • 【网站】如何用Docker容器运行供应商的定制版WordPress

    一、一个烂摊子

    部门此前寻找网站供应商制作了产品网站,其交付网站架构较为老旧,网站基于WordPress 5.0版本构建,PHP版本要求为不高于7.3,MySQL版本5.7。

    就是这种要求在回迁公司服务器时也出现了各种问题。由于公司服务器环境过于杂乱,连mysql5.7的数据库都无法顺利导入。

    这里面也有供应商的一些问题,例如交付的WordPress配置文件与数据库表头不匹配,数据库时间配置错误等。

    在我的帮助下,数据库和配置文件都得以修改正常,网站终于部署上线,但是系统环境导致包含中文文件名的文件无法被解析,在调整Nginx配置无效后,IT让我修改中文名文件,我。。。

    二、服务器和Docker

    借由新ECS服务器和公司官网的搭建,考虑把产品网站也纳入部门服务器的管理。

    但供应商的环境版本老久,为了避免产品网站潜藏的漏洞影响整体服务器的稳定,我使用了Docker来为产品网站配置环境。

    中间也考虑使用LXD来实现,但是网络环境始终无法配置完成,因此不再浪费时间,使用Docker实现功能。

    三、Docker的问题

    最大的问题是镜像源,国内能搜索到的镜像源很多都停止了服务。因此需要在/etc/docker/daemon.json里配置可以访问的镜像源,这个不再赘述。

    四、部署

    将供应商的WP文件夹上传到服务器,可以在同位置配置Docker的yml文件。

    version: '3.7'
    
    services:
      wordpress:
        build: .
        container_name: wordpress-container
        ports:
          - "8000:80"  # WordPress 端口
        volumes:
          - /# 本地 WordPress 目录 wp:/var/www/html  # 本地 WordPress 目录
        networks:
          - wordpress_network
        depends_on:
          - mariadb  # 依赖 MariaDB 服务
        environment:
          WORDPRESS_DB_HOST: mariadb:3306
          WORDPRESS_DB_NAME: wordpress
          WORDPRESS_DB_USER: # 用户名
          WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}  # 从 .env 读取密码
        restart: always
    
      mariadb:
        image: mariadb:latest
        container_name: mariadb-container
        environment:
          MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}  # 从 .env 读取密码
          MYSQL_DATABASE: wordpress
          MYSQL_USER: # 用户名
          MYSQL_PASSWORD: ${MYSQL_PASSWORD}
        volumes:
          - mariadb_data:/var/lib/mysql  # 使用 Docker Volume 代替宿主机路径
          - # 初始数据库地址:/docker-entrypoint-initdb.d/#初始数据库.sql  # 初始 SQL 数据
        ports:
          - "3307:3306"
        networks:
          - wordpress_network
        restart: always
    
      phpmyadmin:
        image: phpmyadmin/phpmyadmin
        container_name: phpmyadmin-container
        environment:
          PMA_HOST: mariadb
          MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}  # 从 .env 读取密码
        ports:
          - "8081:80"
        networks:
          - wordpress_network
        restart: always
    
    networks:
      wordpress_network:
        driver: bridge
    
    volumes:
      mariadb_data:

    从.env文件读取密码:

    MYSQL_ROOT_PASSWORD=# 密码1
    MYSQL_PASSWORD=# 密码2

    如果是使用mariadb,则需要在WP的Config文件中修改配置:

    define('DB_HOST', 'mariadb');

    后端启动之后,我们可以通过IP+端口来进行服务的测试,如果没有问题,就可以通过主机的Nginx代理,来配置域名访问。

    server {
        listen 80;
        server_name #域名;
        return 301 https://$host$request_uri;
    }
    
    server {
        listen 443 ssl;
        server_name #域名;
    
        ssl_certificate /etc/letsencrypt/live/#域名/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/#域名/privkey.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;
    
        location / {
            proxy_pass http://127.0.0.1:8000;#映射docker端口
            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-Host $server_name;
            proxy_set_header X-Forwarded-Proto https;
            proxy_redirect off;
        }
    }
    

    五、其他注意事项:

    1、如果WP的重写规则不可用,检查WP文件夹权限。

    2、如果配置HTTPS发现页面正常,但是管理界面出现问题,考虑是配置文件问题,参考官方说明配置

    define( 'FORCE_SSL_ADMIN', true );
    // in some setups HTTP_X_FORWARDED_PROTO might contain 
    // a comma-separated list e.g. http,https
    // so check for https existence
    if( strpos( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false )
        $_SERVER['HTTPS'] = 'on';
  • 【网站】如何把多站点的WordPress网站从Nginx+PHP-FPM切换到Apache

    最近手搓基于WP架构的企业官网,发现用Nginx+PHP-FPM时,在多站点的情况下可能会有一些地方不容易调试,所以尝试使用Nginx作为代理服务器,Apache作为后端,发现这对WordPress有很好的兼容性。

    那么此前的网站如果已经完成在Nginx+PHP-FPM的部署,如何切换到Nginx+Apache呢?

    这里省略Apache和其PHP模块的配置说明,需要重点修改的有以下几点:

    1、Apache的配置:

    Apache的端口设置,因为我们要使用Nginx转发HTTPS,因此设置Apache的监听端口为8080,避免和Nginx的端口冲突。

    <VirtualHost *:8080>
        DocumentRoot /var/www/html/wordpress
        ServerName yourdomain.com
        <Directory /var/www/html/wordpress>
            AllowOverride All
            Require all granted
        </Directory>
        
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>

    2、WP-Config的配置修改:

    如果网站使用了HTTPS,那么需要按照WordPress的官方设置来进行修改WP-Config:

    define( 'FORCE_SSL_ADMIN', true );
    // in some setups HTTP_X_FORWARDED_PROTO might contain 
    // a comma-separated list e.g. http,https
    // so check for https existence
    if( strpos( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false )
        $_SERVER['HTTPS'] = 'on';

    3、修改Nginx的站点配置文件:

    删除此前用于PHP-FPM的配置代码,把HTTPS转发到Apache处理。

    location / {
        proxy_pass http://127.0.0.1:8080;
        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-Host $server_name;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off;
    }

    4、修改.htaccess文件:

    如果使用子文件夹模式:

    # BEGIN WordPress Multisite
    # Using subfolder network type: https://wordpress.org/documentation/article/htaccess/#multisite
    
    RewriteEngine On
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
    RewriteBase /
    RewriteRule ^index\.php$ - [L]
    
    # add a trailing slash to /wp-admin
    RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
    
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]
    RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
    RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
    RewriteRule . index.php [L]
    
    # END WordPress Multisite
    

    如果使用子域模式:

    # BEGIN WordPress Multisite
    # Using subdomain network type: https://wordpress.org/documentation/article/htaccess/#multisite
    
    RewriteEngine On
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
    RewriteBase /
    RewriteRule ^index\.php$ - [L]
    
    # add a trailing slash to /wp-admin
    RewriteRule ^wp-admin$ wp-admin/ [R=301,L]
    
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]
    RewriteRule ^(wp-(content|admin|includes).*) $1 [L]
    RewriteRule ^(.*\.php)$ $1 [L]
    RewriteRule . index.php [L]
    
    # END WordPress Multisite

    5、修改PHP配置文件:

    选择适合自己的媒体处理限制,因为此前处理媒体的PHP服务是PHP-FPM,切换到Apache后需要配置对应的PHP服务。

    6、检验Nginx配置文件,重启Nginx服务和Apache服务。

  • 【工作】手搓一个基于WordPress的企业官网(1)

    前情提要

    工作以来,我全权负责了企业品牌网站和产品网站的上线全过程,回顾这俩网站,一个基于PHP5一个基于PHP7,漏洞百出且UI基于桌面浏览习惯设计,虽然有移动适配但是不多。

    服务商往往都想在建设和运营上收取double的金钱,而机智的领导们总是在免费的第一年服务午餐吃完后就让网站回迁到公司服务器之上。

    为什么不找供应商

    因为闲(不是

    小公司受限于预算,供应商的水平和投入度都会较低,对接起来身心俱疲。

    贵公司的IT在干嘛?

    OA系统封面加载的5M大小PNG让我对IT心怀敬意(那我问你

    开搞新网站

    去年自己手搓了公司的企业小程序,在移动端效果尚可,同时根据此前的网站后台数据,我们的web端八成流量都来自移动平台。

    因此构建一个适合移动浏览,完全掌握在部门手中的互联网平台成为了计划中的事件。

    为什么选择WordPress

    第一是因为熟悉,NASA、白宫之类的网站都在使用(可以跟领导吹牛逼)

    第二是需要考虑后续的可维护性,WP的生态目前挺好。

    选择服务器

    (1)选择了阿里云的ECS服务器,第一企业域名在阿里云,第二是因为做活动便宜,公司再没钱99也能拿出来吧。

    (2)请第一时间删除阿里云相关的云助手之类的自带软件。若你没有很多的预算购置一些快照服务,自行做好后续的维护。

    部署多站点系统的WP

    由于企业网站需要中英文两个版本,使用不同的域名,因此多站点系统是必须的。

    之前我采有标准的LNMP架构,这次则是在LAMP基础上,使用NGINX做代理,WP的多站点支持对apache2更加友好,PHP版本建议选择WP推荐版本,最新的版本我在使用中还是会出现一些容易BUG的地方。