# 服务配置

properties 服务配置是 FIRERPA 服务的系统配置，它是 **ini** 格式的配置文件。通过编写此文件，您可以让 FIRERPA 在启动时自动连接到 VPN、代理、自动进行 FRP 端口转发或设置登录密码、证书以及其他系统配置等。您可以通过项目中的 [properties.example](https://github.com/firerpa/lamda/blob/HEAD/properties.example) 文件或者下文来检视可配置的项目。

## 文件格式

我们需要为您介绍一下服务端读取服务配置时的处理逻辑以防止您产生混淆。服务配置使用的是标准 **ini** 格式，其中必须包含 `[DEFAULT]` 节，您可以直接在 DEFAULT 节内写入配置项，也可以自己新建一个节来写入配置，这样您可以方便的知道这个配置是哪里来的而不是都放在一起混作一团。
<br>
<br>
现在我们有如下的配置，您可以看到每个节内都有一个 `port` 配置，这是允许的，服务最终会使用 `65001` 作为端口。因为如果不同节中有重复配置，服务在读取时会以最后一个节内的配置为准。所以，如果您觉得配置没有产生作用，可以查看是否是被后续配置覆盖。
```ini
[DEFAULT]
port=65000

[abc]
port=65001
```

所以，参考这个标准，您也可以为每个服务的配置分组，比如像下面这样为 `fwd` 服务创建一个节。
```ini
[DEFAULT]
port=65000

[fwd]
fwd.enable=true
fwd.host=123.123.123.123
fwd.port=9911
fwd.token=abc123
fwd.rport=8080
```


## 配置方式

下面为您介绍服务配置的几种配置方式，通常我们建议您使用 WebUI 进行配置，最不容易出错。但如果您有更高要求如批量部署等场景，WebUI 可能不适合您，您可以参考**手动配置**。

### APP 内配置

APP 内配置相对简单，不过您也需要先编写好配置文件并以文字的形式复制到安装手机上，打开 APP 后转到配置页面，将配置字符串粘贴到编辑框内并点击应用配置按钮即可，但是您需要注意请务必保留 `[DEFAULT]` 节。当然，如果您觉得可能出错，您也可以通过 WebUI 配置。

<p align="center">
<img src="/assets/images/app-config.png" alt="APP 配置" width="35%">
</p>

### WebUI 内配置

您可以直接打开 WebUI 远程桌面，并点击右上角的配置图标进行配置，如下图，您可以进行可视化编辑也可以点击 `Raw Text` 模式进行文本模式编辑。配置完成后可直接点击 `Apply Config` 保存配置，但是服务类配置如代理、FRP 等将不会生效，如您想立即生效，请勾选 `Reload Service` 后再点击 `Apply Config` 按钮，这将会完全重载服务端，您的远程桌面也会暂时断连。

<p align="center">
<img src="/assets/images/webui-config.png" alt="WebUI 配置">
</p>

### 手动配置

手动配置需要注意您编写的配置文件格式合法，否则服务将不会使用您的配置。首先您需要确保配置文件包含 `[DEFAULT]` 节，即使这个节可能没有配置。其次确保您使用的编辑器不会添加额外的隐藏字符，请不要使用 notepad 等基础编辑器编写。一个合法的配置文件应该使用 uft-8 编码，并严格确保换行符为 `\n` 或者 `\r\n`，我们建议使用 `\n` 换行。一个示例的配置文件如下。

```ini
[DEFAULT]

[fwd]
fwd.enable=true
fwd.host=123.123.123.123
fwd.port=9911
fwd.token=abc123
fwd.rport=8080
```

或者如果您觉得麻烦，直接全塞到 DEFAULT 节内也算完全可以的。

```ini
[DEFAULT]
fwd.enable=true
fwd.host=123.123.123.123
fwd.port=9911
fwd.token=abc123
fwd.rport=8080
```

当您的配置文件编写完成后，您需要手动将配置文件放到手机上的特定目录。默认情况下分为两种，如果您的服务端是准备使用 root 身份启动的，那么配置文件应该存储于 `/data/usr/.local/`，如果是 shell 身份，则存储于 `/data/local/tmp/usr/.local/`。您只需要确保对应目录存在，如果不存在可以手动创建，随后将配置文件重命名为 `properties` 并使用 adb push 到对应目录即可。

```{attention}
这里有个特殊情况，如果您使用的是 APP 部署的服务，由于 APP 会使用一个随机的父级目录作为服务运行目录，导致配置文件目录具有随机性，所以您无法对设备统一进行配置。
```

## 配置参数

以下配置为服务端完整可用的配置项目，请勿直接复制该内容，仅挑选您需要的部分或者服务进行复制修改，直接复制完整内容可能会导致服务异常。

```ini
[DEFAULT]
port=65000                      ; 设置服务的监听端口。

; webui.* 键只允许在 DEFAULT 节中使用，您可以预设远程桌面的各种参数。

webui.darkmode = off            ; 是否启用远程桌面深色主题。
webui.audio = on                ; 是否启用远程桌面音频（需要 Android 10+）。
webui.upload-path = /data/local/tmp/uploads ; 设置远程桌面拖放上传的默认目录（目录必须存在）。
webui.share-clipboard = off     ; 是否启用远程桌面双向剪贴板共享。
webui.touch.use-screen-size = off ; 使用原始屏幕尺寸计算触摸坐标（特殊情况下启用）。
webui.webrtc = on               ; 是否启用远程桌面 WebRTC。

; 设置 WebRTC STUN/TURN 服务器地址（多个地址用逗号分隔）。
; 示例 stun 服务器：stun:stun.device-farm.com
; 示例 turn 服务器：turn://user:pass@example.com:3478?transport=tcp
webui.webrtc.ice-server = stun:stun.device-farm.com 

webui.video.h264 = on           ; 是否启用 H264 编码。
webui.video.backend = 0         ; 设置视频后端实现（0=默认，1=硬件）。
webui.video.scale = 0.5         ; 设置视频缩放比例（0.1-1.0，1.0 表示全分辨率）。
webui.video.quality = 50        ; 设置视频质量（10-100）。
webui.video.fps = 35            ; 设置期望的视频帧率（10-60)。

; 设置服务证书。它将加密您的远程桌面和 API 流量，并启用密码认证。您可以通过执行 'base64 -w0 lamda.pem' 来获取以下配置值。
cert=TEFNREEgU1NMIENFUlRJRklDQVRFIChDTj10ZXN0LFBBU1NXRD1hMWMwZTNlYTcwN2E1NGRlN2EwZjk1KQotLS0tLUJFR0lOIFBSSVZBVEUgS0VZLS0tLS0KTUlJRXZnSUJBREFOQmdrcWhraUc5dzBCQVFFRkFBU0NCS2d3Z2dTa0FnRUFBb0lCQVFEVmNMWlA5b0xRWkRIRgp5V0pTa2U0Z0crSUpmSCtMWlk0cXUzdS9OckRwSHZCN2k5V01rMWxRL2FMSGI0V3ZqelBLK1RITm9rRzc2MENRClhBTUpWS0dmYXRwcmNLUXdvMGhvWDZ2NlhsTVlZUlNRbW9wN3pSaUtnN3ZxKzV2S09DQ2RKcDFlSVNiZXcyTEgKTmYxL3JZelpwa1Q1bHoxTGZkem00eXJBS3VNa0tyZ3pnTzJRcE9CQVdYdmdiWG9BMDdidDdOODZZOGdNZFUwdAp6Ui9EcmhLTi9JMVdYSk11MU4wQW5UbDJRdEhEb0dCN0UyS0xpdmwybDZJdnRrYWJ4RE55Y2lHbUxOUGlMRklrCllPSHlnMUg3MUJ2NU04NE5TWDc1c2xuOXVNUGUzOVNFVlJoU0ptNHcvT2tXZnA5dGpZRUx3dHphdFhoSWJoS3MKaC9OZU1lOWRBZ01CQUFFQ2dnRUFCYlFuWUdlcFdKYjAydURtSnhLNGx2OFNhL0o1dzJpSldMYjk0dW1SUExRKwpTa1E5c1Zpc0JiQU1JNHc2dWFyNEFBVTh3WGxaTndPekMvM2V6dWNHRXFreEFReXM0VDB4SXRPUkF2WExxVlowCkl1WnpxNW53Si9OeFFzeEtmaWhBZkRLYlRmZjdmcG5MWlV0dlpNbG5LWUhQVExtRlFua3drckwyRE5YdDVVOTYKYXJUUDVOY0x1aDQ2dU93alJUOWhaNytYQi9ubU9LeTV4V3hoNWVMQmJJUTJrS0UvdWViUlVYRGZNdG5tbTh2aApRSG9VM3N5dzlZcE1xRDlWQWppcGlqQXRwbUlwa2w1emRWSE52Q1dCSGk2NjZxKzF6cUpHeFVUODBseHo1N2R1ClRvRFFQc1l0OFFEL3ZjNGkxajd0bDZyRzNQWkJNM05LNVR5ZFYyRnlnUUtCZ1FEYUcycnV3aWxyYUdZRzZNQWwKNEF2WW1BY0hHQWUwQjR0ZmtkdS9QandlRWQyWUF2TjJIQWV1Z1ZUSWg1eFplUlIwNFE4ZVNGenBTaEpwREpkNAp1TEhHcXJ2cmpXL1greEVIc081NnNjNjRiem1weWJWQXBlQnA4NlFGSTk4V3FmZkFyN3FzbzhweFJjNmdTRU1uCk5TcXV1Z2psYU05TlJmcUo4ci82RklmQkxRS0JnUUQ2aGJ0Z2dIdVJoTHhHYWNNaERvOVppcXJlNi9HN1dvZnQKR2FGZmFQM2xZNTNmM0hPdSsyNTZMWDY1ZWFYRTdrbXlQOGRDM2VWL24xT3dvTHdBYm1BZ2pEWVd1N09KdGk4QQpPbG9VNmtnTkVwNWcwOHpVWlBaR3NSMkZMd2VpUkgrQ3ZOdFBZakJydmFIQUtVU2lLa3BKdEpWeFpIdUl6SlpGCjVUZkM2VjNrOFFLQmdEeWp0TlpPKzA4V2hvOVROT0VTNnBnOHBHK1BlY3pPOEN3UkZJU1dYQWFNTnd6bGZTVVEKWS81YmpPUDMrRHRVRTZEdlZkRzRrc1IxeUtxV1NxTFF6dlNLVVpjTEN0YUV3bFplRmQvZEFibDdpdyt1dWdzUQpVMVdCM005bENzaDFWeUdtZWdNM3dyZzlqVlk0NFJyTWlHSnQ3TDFEcDZjM1ZwSDJBUFFac3lpOUFvR0JBTk9pCmpmeWtEYitNNXBDRllEWlkybmpHVURzcUQzZzZyb0Y2R1gxRWNOaU1JeDZ1V1h3RkkvdEsyN2RNTU9JQWUzbDkKcjVPcGFPczdhYlBZMVhsM3hQVTUvYWVPd2NrZ2d1d3FYMWN6NDlKSFhFeG9JSzE4N1NBakY5RWZQYyt6RmhVWAovaDA5MGJIeTdPWXM5cklZRDlIY0lETStzNjJKUjVtY1hsTG1Xay9CQW9HQkFKRVhQV05IWEwra1l6My91R1c3CnRKd0hUQzFlbEJjclcvaHpJMWt4ZEhXem5VaXNTWlcyVnA5b0wwSWNrQXVWQkx6eGUvR1h6OGJRTjZkOWwyZDAKdGtmUmo1TmpDOTUzS2N1cTNSekRmVU40cTcyUlVWTWlFOHVvSTBkVVZpalczN0tVMEhLcm1pbDBocU01eW9iNQpVZlhPQ2Q5SlRRSWx5Y2dNWER6Tm00S3oKLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0KTUlJQ3FEQ0NBWkNnQXdJQkFnSVJBUHNjMVBRNXBuSDNhNk1GZkdVTXA2WXdEUVlKS29aSWh2Y05BUUVMQlFBdwpFREVPTUF3R0ExVUVDZ3dGVEVGTlJFRXdIaGNOTWpBd01UQXhNREF3TURBeFdoY05Namt4TWpJNU1EQXdNREF4CldqQVBNUTB3Q3dZRFZRUUREQVIwWlhOME1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQTFYQzJUL2FDMEdReHhjbGlVcEh1SUJ2aUNYeC9pMldPS3J0N3Z6YXc2Ujd3ZTR2VmpKTlpVUDJpeDIrRgpyNDh6eXZreHphSkJ1K3RBa0Z3RENWU2huMnJhYTNDa01LTklhRityK2w1VEdHRVVrSnFLZTgwWWlvTzc2dnViCnlqZ2duU2FkWGlFbTNzTml4elg5ZjYyTTJhWkUrWmM5UzMzYzV1TXF3Q3JqSkNxNE00RHRrS1RnUUZsNzRHMTYKQU5PMjdlemZPbVBJREhWTkxjMGZ3NjRTamZ5TlZseVRMdFRkQUowNWRrTFJ3NkJnZXhOaWk0cjVkcGVpTDdaRwptOFF6Y25JaHBpelQ0aXhTSkdEaDhvTlIrOVFiK1RQT0RVbCsrYkpaL2JqRDN0L1VoRlVZVWladU1QenBGbjZmCmJZMkJDOExjMnJWNFNHNFNySWZ6WGpIdlhRSURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBWEQ0L1cKQjBhSW1aWGpQbTRxUnBOazJmUnpjU1g4MGw2TlZaWWxJV3ZYalFxUXdXZnMvSGczZDVzYUpickFmcWVPa1lQdQpjeXJEWFZPdC9RTEVDOTFBSGtjRWJ1R0dPMGNFU2YyOHdUM1UzRnJJb2cxS1VyTURqWFFIb09vZEJpOGdNaVBmCmROcWhMSTdkNDJBTXJKU3dZUTlSUG9vWG9UZ2xDa0d3R291RDhuS0V5MmNHeVMxM3lQcDRseC9TWTR1QkRFU0sKRlErR0ZRTExGQktQZHZNc2x0cHYyQWFMWmR3clF4aFQ2aTU1U1puNStLb3c1TGxYL0RHdUw5UnRPdmZ2T0tzZQpRZ3pOQUg3QkYzbGdvQmJjYk9yZkVQazY1ZEZRN0NXYi91aDZjVmlmSjdxQzkvL0xhdElmb1VQVnJiRXdZL2dRCk5BRXFYclduMGZuYUc0cUEKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0KTUlJQ2xEQ0NBWHdDQVFBd0RRWUpLb1pJaHZjTkFRRUxCUUF3RURFT01Bd0dBMVVFQ2d3RlRFRk5SRUV3SGhjTgpNakF3TVRBeE1EQXdNREF4V2hjTk1qa3hNakk1TURBd01EQXhXakFRTVE0d0RBWURWUVFLREFWTVFVMUVRVENDCkFTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTG5xZkJadnJHWmFxZ2s1bXNDUlJwUHoKcC8rNDY0akJrbmxtVEtldE9ja0RUVXE4VjZmSC8yR2ZiNkhqam9ENXBrQ3RENW1TS2thSE5odXhMWHNGZkVmYwpLbG1ubjNacGp5Tk9IRUEvaUFPMkR5RVlhMDh4U2V2TTdXb2piRjdjTmo1L0RZZzdlYjBpMCsvL2JCbGg4bmxPCmdoU1VoQ1RNNVBDb2ZMRFU4c1ZYdVlBaUdVNlV6QnJJQzB2SEVsdERraUpWTHBjQ3RzS2pFWk9za1BkQWM3dTYKL2FBMFA1R29uWjVVa1JEWXBhK2plSlVhYnFXWlFRRWd0bXZqbG1VVWlYd3UwalJuajFuMFQzZlBRRDNnQStMSQp2QUU5dmd2cFk1WFFqNm90cEJ2c1ozTUpKTktjVU1RdTF6T0FOVHpPMThUbEE4S29CTnNCeThaOURRWktYRjhDCkF3RUFBVEFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBZUduL055cUlSSS8wQUdxdkhQOTdLdFE3NlRqNmFjaGIKMzBMSVhXcCtZSFVhTWVBVmpkMlo3alNRcDVtWlpGbCtrMWZiMzM3SWVhR1hvZlZJMjFlSzUyUVgydGVOb0JrQQovVi9PMUh1MzUvK2FpejB4c2RENndXdndvNEZ5MWpsbWFlSmh3ZFFhY0JsREdGQTJqRkp4dUVwYWhmeFp2VXNiCjNqNXpVMFdLVFVDZkVEZ1hGd0J3MTJ4a3UvN1RNZENFYlJzWWFaM3pGVEMyMjZsUWJVRE43d2VxRndTRCt0QjYKUnVoSXhlOCtjRndBc0FXSENsZXJLZ1pucjN0NVFGMDc4cFcyR0h5OENzSjdWM01aVDVsWjQzbFM1TklCOUp6WgpTWXhaL2l6aFJ5aDVxUjczdUFnc0phTDU2QmorY1Fxbm9UcWhMWlZsN0orTTZXaFdLem9qc0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==

; 设置自定义远程桌面登录密码，6-32 个字符，便于记忆，该密码仅在使用了服务证书时生效。
ssl-web-credential=password123

; 设置 firerpa WebUI 及其 API 的 Access-Control-Allow-Origin 头，允许您将 firerpa 的功能嵌入到您的 Web 应用中。
; 请参阅 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
allow_origin=https://example.com

; 如果远程桌面上触摸屏幕出现偏移或无响应，请将 touch.backend 设置为 system，可用选项：system | native（默认）
touch.backend=system

; 设置服务日志文件（目录必须存在）
logfile=/data/local/tmp/server.log

; 请勿手动编写以下配置。您应使用我们配套的 OpenVPN 服务器部署方案进行设置，并使用其内置命令生成此配置。
[openvpn]
openvpn.proto=udp
openvpn.cipher=AES-256-GCM
openvpn.host=123.123.123.123
openvpn.port=1190
openvpn.ca=LS0tLS1CRU...
openvpn.cert=LS0tLS1CRU...
openvpn.key=LS0tLS1CRU...
openvpn.tls_encryption=
openvpn.tls_key_direction=
openvpn.tls_key=

; 以下配置项仅可手动配置。
openvpn.global=false            ; 是否启用全局 VPN。
openvpn.enable=true             ; 是否启用服务 true | false

; 此配置用于让设备在启动时自动使用代理服务器。
[gproxy]
gproxy.enable=true              ; 是否启用服务 true | false
gproxy.type=http-connect        ; 代理类型，可选 http-connect、https-connect、socks5、shadowsocks
gproxy.host=172.1.1.1           ; 代理服务器地址
gproxy.port=8080                ; 代理服务器端口
gproxy.password=                ; 代理服务器登录密码（留空表示无需认证）
gproxy.login=                   ; 代理服务器登录用户名（留空表示无需认证，若类型为 shadowsocks 则为加密方式）
gproxy.nameserver=              ; 自定义 DNS 服务器
gproxy.drop_udp=false           ; 是否丢弃 UDP 数据包。
gproxy.udp_proxy=false          ; 是否代理 UDP 数据包（需要代理支持，如 socks5、shadowsocks）。
gproxy.bypass_local_subnet=true ; 不代理本地局域网流量。
gproxy.dns_proxy=false          ; 使 DNS 查询通过代理（需要支持 UDP 和 TCP 的 DNS 服务器）。
gproxy.uid=                     ; 仅对指定 UID 进行代理（默认为全局）。

[cron]
cron.enable=true                ; 是否启用服务 true | false

[sshd]
sshd.enable=true                ; 是否启用服务 true | false

[fwd]
fwd.enable=true                 ; 是否启用服务 true | false
fwd.rport=0                     ; 转发到远程的端口（0 表示随机分配）
fwd.host=123.123.123.123        ; FRP 服务器地址
fwd.port=9911                   ; FRP 服务器端口
fwd.protocol=tcp                ; FRP 协议
fwd.token=abc123                ; FRP 登录认证（token）

[adb]
adb.enable=true                 ; 是否启用服务 true | false
adb.directory=/data/local/tmp   ; 内置 ADB 的默认工作目录（adb shell 工作目录）
; 警告：如果设置为 true，ADB 连接将拥有 root 权限，否则将拥有 shell 权限。当此选项设置为 false 时，
; 您将使用类似原生的 adb shell，并且无法使用内置命令。请注意，由于 ADB 不使用 TLS 连接，流量可能被监控。出于安全考虑，当服务使用证书启动时，此值将默认设置为 false。但是，如果您在 properties.local 文件中指定了它，文件中的配置将优先，您有责任确保安全性。
adb.privileged=true

[tunnel2]
tunnel2.enable=true             ; 是否启用服务 true | false
; 只有同时设置了登录名和密码时，网桥代理才需要登录认证，如果任一留空，则无需登录认证。
tunnel2.login=lamda
tunnel2.password=1234           ; 网桥代理的登录密码
; 出站接口（rmnet|wlan）当出站接口为 rmnet 时，代理将尝试通过移动数据转发您的请求。当出站接口为 wlan 时，请求将通过 wlan 接口转发。如果配置为空，将使用默认网络转发请求。
tunnel2.iface=rmnet

[mdns]
mdns.enable=false               ; 启用或禁用 true | false
mdns.meta=false                 ; 为 mDNS 添加 TXT 元数据。启用后，将支持使用 python-zeroconf 等工具查询设备信息，如型号、ABI 和设备 ID。默认禁用。
mdns.name=DEVICEID-UNIQUE.lamda ; 使用本地唯一 ID 设置广播域名，默认为 {DEVICEID-UNIQUE}.lamda。如果本地网络中名称重复，将自动添加后缀 ID。
mdns.service=lamda              ; 设置广播服务名称，默认为 lamda，即 _lamda._tcp.local。
```