1{ pkgs, lib, config, ... }:
2
3with lib;
4let
5 cfg = config.services.gammu-smsd;
6
7 configFile = pkgs.writeText "gammu-smsd.conf" ''
8 [gammu]
9 Device = ${cfg.device.path}
10 Connection = ${cfg.device.connection}
11 SynchronizeTime = ${if cfg.device.synchronizeTime then "yes" else "no"}
12 LogFormat = ${cfg.log.format}
13 ${optionalString (cfg.device.pin != null) "PIN = ${cfg.device.pin}"}
14 ${cfg.extraConfig.gammu}
15
16
17 [smsd]
18 LogFile = ${cfg.log.file}
19 Service = ${cfg.backend.service}
20
21 ${optionalString (cfg.backend.service == "files") ''
22 InboxPath = ${cfg.backend.files.inboxPath}
23 OutboxPath = ${cfg.backend.files.outboxPath}
24 SentSMSPath = ${cfg.backend.files.sentSMSPath}
25 ErrorSMSPath = ${cfg.backend.files.errorSMSPath}
26 ''}
27
28 ${optionalString (cfg.backend.service == "sql" && cfg.backend.sql.driver == "sqlite") ''
29 Driver = ${cfg.backend.sql.driver}
30 DBDir = ${cfg.backend.sql.database}
31 ''}
32
33 ${optionalString (cfg.backend.service == "sql" && cfg.backend.sql.driver == "native_pgsql") (
34 with cfg.backend; ''
35 Driver = ${sql.driver}
36 ${optionalString (sql.database!= null) "Database = ${sql.database}"}
37 ${optionalString (sql.host != null) "Host = ${sql.host}"}
38 ${optionalString (sql.user != null) "User = ${sql.user}"}
39 ${optionalString (sql.password != null) "Password = ${sql.password}"}
40 '')}
41
42 ${cfg.extraConfig.smsd}
43 '';
44
45 initDBDir = "share/doc/gammu/examples/sql";
46
47 gammuPackage = with cfg.backend; (pkgs.gammu.override {
48 dbiSupport = service == "sql" && sql.driver == "sqlite";
49 postgresSupport = service == "sql" && sql.driver == "native_pgsql";
50 });
51
52in {
53 options = {
54 services.gammu-smsd = {
55
56 enable = mkEnableOption (lib.mdDoc "gammu-smsd daemon");
57
58 user = mkOption {
59 type = types.str;
60 default = "smsd";
61 description = lib.mdDoc "User that has access to the device";
62 };
63
64 device = {
65 path = mkOption {
66 type = types.path;
67 description = lib.mdDoc "Device node or address of the phone";
68 example = "/dev/ttyUSB2";
69 };
70
71 group = mkOption {
72 type = types.str;
73 default = "root";
74 description = lib.mdDoc "Owner group of the device";
75 example = "dialout";
76 };
77
78 connection = mkOption {
79 type = types.str;
80 default = "at";
81 description = lib.mdDoc "Protocol which will be used to talk to the phone";
82 };
83
84 synchronizeTime = mkOption {
85 type = types.bool;
86 default = true;
87 description = lib.mdDoc "Whether to set time from computer to the phone during starting connection";
88 };
89
90 pin = mkOption {
91 type = types.nullOr types.str;
92 default = null;
93 description = lib.mdDoc "PIN code for the simcard";
94 };
95 };
96
97
98 log = {
99 file = mkOption {
100 type = types.str;
101 default = "syslog";
102 description = lib.mdDoc "Path to file where information about communication will be stored";
103 };
104
105 format = mkOption {
106 type = types.enum [ "nothing" "text" "textall" "textalldate" "errors" "errorsdate" "binary" ];
107 default = "errors";
108 description = lib.mdDoc "Determines what will be logged to the LogFile";
109 };
110 };
111
112
113 extraConfig = {
114 gammu = mkOption {
115 type = types.lines;
116 default = "";
117 description = lib.mdDoc "Extra config lines to be added into [gammu] section";
118 };
119
120
121 smsd = mkOption {
122 type = types.lines;
123 default = "";
124 description = lib.mdDoc "Extra config lines to be added into [smsd] section";
125 };
126 };
127
128
129 backend = {
130 service = mkOption {
131 type = types.enum [ "null" "files" "sql" ];
132 default = "null";
133 description = lib.mdDoc "Service to use to store sms data.";
134 };
135
136 files = {
137 inboxPath = mkOption {
138 type = types.path;
139 default = "/var/spool/sms/inbox/";
140 description = lib.mdDoc "Where the received SMSes are stored";
141 };
142
143 outboxPath = mkOption {
144 type = types.path;
145 default = "/var/spool/sms/outbox/";
146 description = lib.mdDoc "Where SMSes to be sent should be placed";
147 };
148
149 sentSMSPath = mkOption {
150 type = types.path;
151 default = "/var/spool/sms/sent/";
152 description = lib.mdDoc "Where the transmitted SMSes are placed";
153 };
154
155 errorSMSPath = mkOption {
156 type = types.path;
157 default = "/var/spool/sms/error/";
158 description = lib.mdDoc "Where SMSes with error in transmission is placed";
159 };
160 };
161
162 sql = {
163 driver = mkOption {
164 type = types.enum [ "native_mysql" "native_pgsql" "odbc" "dbi" ];
165 description = lib.mdDoc "DB driver to use";
166 };
167
168 sqlDialect = mkOption {
169 type = types.nullOr types.str;
170 default = null;
171 description = lib.mdDoc "SQL dialect to use (odbc driver only)";
172 };
173
174 database = mkOption {
175 type = types.nullOr types.str;
176 default = null;
177 description = lib.mdDoc "Database name to store sms data";
178 };
179
180 host = mkOption {
181 type = types.str;
182 default = "localhost";
183 description = lib.mdDoc "Database server address";
184 };
185
186 user = mkOption {
187 type = types.nullOr types.str;
188 default = null;
189 description = lib.mdDoc "User name used for connection to the database";
190 };
191
192 password = mkOption {
193 type = types.nullOr types.str;
194 default = null;
195 description = lib.mdDoc "User password used for connection to the database";
196 };
197 };
198 };
199 };
200 };
201
202 config = mkIf cfg.enable {
203 users.users.${cfg.user} = {
204 description = "gammu-smsd user";
205 isSystemUser = true;
206 group = cfg.device.group;
207 };
208
209 environment.systemPackages = with cfg.backend; [ gammuPackage ]
210 ++ optionals (service == "sql" && sql.driver == "sqlite") [ pkgs.sqlite ];
211
212 systemd.services.gammu-smsd = {
213 description = "gammu-smsd daemon";
214
215 wantedBy = [ "multi-user.target" ];
216
217 wants = with cfg.backend; [ ]
218 ++ optionals (service == "sql" && sql.driver == "native_pgsql") [ "postgresql.service" ];
219
220 preStart = with cfg.backend;
221
222 optionalString (service == "files") (with files; ''
223 mkdir -m 755 -p ${inboxPath} ${outboxPath} ${sentSMSPath} ${errorSMSPath}
224 chown ${cfg.user} -R ${inboxPath}
225 chown ${cfg.user} -R ${outboxPath}
226 chown ${cfg.user} -R ${sentSMSPath}
227 chown ${cfg.user} -R ${errorSMSPath}
228 '')
229 + optionalString (service == "sql" && sql.driver == "sqlite") ''
230 cat "${gammuPackage}/${initDBDir}/sqlite.sql" \
231 | ${pkgs.sqlite.bin}/bin/sqlite3 ${sql.database}
232 ''
233 + (let execPsql = extraArgs: concatStringsSep " " [
234 (optionalString (sql.password != null) "PGPASSWORD=${sql.password}")
235 "${config.services.postgresql.package}/bin/psql"
236 (optionalString (sql.host != null) "-h ${sql.host}")
237 (optionalString (sql.user != null) "-U ${sql.user}")
238 "$extraArgs"
239 "${sql.database}"
240 ]; in optionalString (service == "sql" && sql.driver == "native_pgsql") ''
241 echo '\i '"${gammuPackage}/${initDBDir}/pgsql.sql" | ${execPsql ""}
242 '');
243
244 serviceConfig = {
245 User = "${cfg.user}";
246 Group = "${cfg.device.group}";
247 PermissionsStartOnly = true;
248 ExecStart = "${gammuPackage}/bin/gammu-smsd -c ${configFile}";
249 };
250
251 };
252 };
253}