diff options
author | Hsieh Chin Fan <typebrook@gmail.com> | 2022-02-02 13:34:47 +0800 |
---|---|---|
committer | Hsieh Chin Fan <pham@topo.tw> | 2024-11-30 21:09:29 +0800 |
commit | 9934dd538b0ce116e3b1600272cb46369b082246 (patch) | |
tree | 2f28c6c362201151eaf8218e566479ed7eb72070 |
init commit
45 files changed, 3303 insertions, 0 deletions
diff --git a/demo/client.sh b/demo/client.sh new file mode 100644 index 0000000..5d4a3c4 --- /dev/null +++ b/demo/client.sh | |||
@@ -0,0 +1,30 @@ | |||
1 | # Enter tmux session on this host | ||
2 | |||
3 | # RUN the following command to quickly execute this script | ||
4 | # curl demo.topo.tw | sh | ||
5 | |||
6 | # Add private key as temporary file | ||
7 | # Remove it when script is exited | ||
8 | IDENTITY_FILE=$(mktemp -t demo.key.XXXX) | ||
9 | trap "rm $IDENTITY_FILE" EXIT | ||
10 | |||
11 | # This private key can only run command 'tmux -r' on remote | ||
12 | <<KEY cat >$IDENTITY_FILE | ||
13 | -----BEGIN OPENSSH PRIVATE KEY----- | ||
14 | b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS | ||
15 | 1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQR4XNnhI1OJe4o/yexrMJs3EECymgz4 | ||
16 | UjF9oHl3F+jF/CQ5EDyFaW1IH35Eh0ECHPDfqfzB0BmgZ4zqOs9lvzA2AAAAqPeejtr3no | ||
17 | 7aAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHhc2eEjU4l7ij/J | ||
18 | 7GswmzcQQLKaDPhSMX2geXcX6MX8JDkQPIVpbUgffkSHQQIc8N+p/MHQGaBnjOo6z2W/MD | ||
19 | YAAAAhALHPQcjhYNBkrVVzDj6dJbRbN2gqAiJtXPx/iJogfcaqAAAACnBoYW1AdnVsdHIB | ||
20 | AgMEBQ== | ||
21 | -----END OPENSSH PRIVATE KEY----- | ||
22 | KEY | ||
23 | |||
24 | # Launch SSH connection with private key above | ||
25 | # Use tty of parent shell as STDIN, so user cannot type on the screen | ||
26 | </proc/$PPID/fd/0 ssh -i $IDENTITY_FILE \ | ||
27 | -o StrictHostKeyChecking=no \ | ||
28 | -o UserKnownHostsFile=/dev/null \ | ||
29 | -p 7579 \ | ||
30 | pham@git.topo.tw | ||
diff --git a/dovecot/90-sieve.conf b/dovecot/90-sieve.conf new file mode 100644 index 0000000..8c0c244 --- /dev/null +++ b/dovecot/90-sieve.conf | |||
@@ -0,0 +1,206 @@ | |||
1 | ## | ||
2 | ## Settings for the Sieve interpreter | ||
3 | ## | ||
4 | |||
5 | # Do not forget to enable the Sieve plugin in 15-lda.conf and 20-lmtp.conf | ||
6 | # by adding it to the respective mail_plugins= settings. | ||
7 | |||
8 | # The Sieve interpreter can retrieve Sieve scripts from several types of | ||
9 | # locations. The default `file' location type is a local filesystem path | ||
10 | # pointing to a Sieve script file or a directory containing multiple Sieve | ||
11 | # script files. More complex setups can use other location types such as | ||
12 | # `ldap' or `dict' to fetch Sieve scripts from remote databases. | ||
13 | # | ||
14 | # All settings that specify the location of one ore more Sieve scripts accept | ||
15 | # the following syntax: | ||
16 | # | ||
17 | # location = [<type>:]path[;<option>[=<value>][;...]] | ||
18 | # | ||
19 | # If the type prefix is omitted, the script location type is 'file' and the | ||
20 | # location is interpreted as a local filesystem path pointing to a Sieve script | ||
21 | # file or directory. Refer to Pigeonhole wiki or INSTALL file for more | ||
22 | # information. | ||
23 | |||
24 | plugin { | ||
25 | # The location of the user's main Sieve script or script storage. The LDA | ||
26 | # Sieve plugin uses this to find the active script for Sieve filtering at | ||
27 | # delivery. The "include" extension uses this location for retrieving | ||
28 | # :personal" scripts. This is also where the ManageSieve service will store | ||
29 | # the user's scripts, if supported. | ||
30 | # | ||
31 | # Currently only the 'file:' location type supports ManageSieve operation. | ||
32 | # Other location types like 'dict:' and 'ldap:' can currently only | ||
33 | # be used as a read-only script source (). | ||
34 | # | ||
35 | # For the 'file:' type: use the ';active=' parameter to specify where the | ||
36 | # active script symlink is located. | ||
37 | # For other types: use the ';name=' parameter to specify the name of the | ||
38 | # default/active script. | ||
39 | sieve = file:~/sieve;active=~/.dovecot.sieve | ||
40 | |||
41 | # The default Sieve script when the user has none. This is the location of a | ||
42 | # global sieve script file, which gets executed ONLY if user's personal Sieve | ||
43 | # script doesn't exist. Be sure to pre-compile this script manually using the | ||
44 | # sievec command line tool if the binary is not stored in a global location. | ||
45 | # --> See sieve_before for executing scripts before the user's personal | ||
46 | # script. | ||
47 | #sieve_default = /var/lib/dovecot/sieve/default.sieve | ||
48 | |||
49 | # The name by which the default Sieve script (as configured by the | ||
50 | # sieve_default setting) is visible to the user through ManageSieve. | ||
51 | #sieve_default_name = | ||
52 | |||
53 | # Location for ":global" include scripts as used by the "include" extension. | ||
54 | #sieve_global = | ||
55 | |||
56 | # The location of a Sieve script that is run for any message that is about to | ||
57 | # be discarded; i.e., it is not delivered anywhere by the normal Sieve | ||
58 | # execution. This only happens when the "implicit keep" is canceled, by e.g. | ||
59 | # the "discard" action, and no actions that deliver the message are executed. | ||
60 | # This "discard script" can prevent discarding the message, by executing | ||
61 | # alternative actions. If the discard script does nothing, the message is | ||
62 | # still discarded as it would be when no discard script is configured. | ||
63 | #sieve_discard = | ||
64 | |||
65 | # Location Sieve of scripts that need to be executed before the user's | ||
66 | # personal script. If a 'file' location path points to a directory, all the | ||
67 | # Sieve scripts contained therein (with the proper `.sieve' extension) are | ||
68 | # executed. The order of execution within that directory is determined by the | ||
69 | # file names, using a normal 8bit per-character comparison. | ||
70 | # | ||
71 | # Multiple script locations can be specified by appending an increasing number | ||
72 | # to the setting name. The Sieve scripts found from these locations are added | ||
73 | # to the script execution sequence in the specified order. Reading the | ||
74 | # numbered sieve_before settings stops at the first missing setting, so no | ||
75 | # numbers may be skipped. | ||
76 | #sieve_before = /var/lib/dovecot/sieve.d/ | ||
77 | #sieve_before2 = ldap:/etc/sieve-ldap.conf;name=ldap-domain | ||
78 | #sieve_before3 = (etc...) | ||
79 | |||
80 | # Identical to sieve_before, only the specified scripts are executed after the | ||
81 | # user's script (only when keep is still in effect!). Multiple script | ||
82 | # locations can be specified by appending an increasing number. | ||
83 | #sieve_after = | ||
84 | #sieve_after2 = | ||
85 | #sieve_after2 = (etc...) | ||
86 | |||
87 | # Which Sieve language extensions are available to users. By default, all | ||
88 | # supported extensions are available, except for deprecated extensions or | ||
89 | # those that are still under development. Some system administrators may want | ||
90 | # to disable certain Sieve extensions or enable those that are not available | ||
91 | # by default. This setting can use '+' and '-' to specify differences relative | ||
92 | # to the default. For example `sieve_extensions = +imapflags' will enable the | ||
93 | # deprecated imapflags extension in addition to all extensions were already | ||
94 | # enabled by default. | ||
95 | sieve_extensions = +variables +editheader | ||
96 | sieve_editheader_max_header_size = 1k | ||
97 | |||
98 | # Which Sieve language extensions are ONLY available in global scripts. This | ||
99 | # can be used to restrict the use of certain Sieve extensions to administrator | ||
100 | # control, for instance when these extensions can cause security concerns. | ||
101 | # This setting has higher precedence than the `sieve_extensions' setting | ||
102 | # (above), meaning that the extensions enabled with this setting are never | ||
103 | # available to the user's personal script no matter what is specified for the | ||
104 | # `sieve_extensions' setting. The syntax of this setting is similar to the | ||
105 | # `sieve_extensions' setting, with the difference that extensions are | ||
106 | # enabled or disabled for exclusive use in global scripts. Currently, no | ||
107 | # extensions are marked as such by default. | ||
108 | #sieve_global_extensions = | ||
109 | |||
110 | # The Pigeonhole Sieve interpreter can have plugins of its own. Using this | ||
111 | # setting, the used plugins can be specified. Check the Dovecot wiki | ||
112 | # (wiki2.dovecot.org) or the pigeonhole website | ||
113 | # (http://pigeonhole.dovecot.org) for available plugins. | ||
114 | # The sieve_extprograms plugin is included in this release. | ||
115 | #sieve_plugins = | ||
116 | |||
117 | # The maximum size of a Sieve script. The compiler will refuse to compile any | ||
118 | # script larger than this limit. If set to 0, no limit on the script size is | ||
119 | # enforced. | ||
120 | #sieve_max_script_size = 1M | ||
121 | |||
122 | # The maximum number of actions that can be performed during a single script | ||
123 | # execution. If set to 0, no limit on the total number of actions is enforced. | ||
124 | #sieve_max_actions = 32 | ||
125 | |||
126 | # The maximum number of redirect actions that can be performed during a single | ||
127 | # script execution. If set to 0, no redirect actions are allowed. | ||
128 | #sieve_max_redirects = 4 | ||
129 | |||
130 | # The maximum number of personal Sieve scripts a single user can have. If set | ||
131 | # to 0, no limit on the number of scripts is enforced. | ||
132 | # (Currently only relevant for ManageSieve) | ||
133 | #sieve_quota_max_scripts = 0 | ||
134 | |||
135 | # The maximum amount of disk storage a single user's scripts may occupy. If | ||
136 | # set to 0, no limit on the used amount of disk storage is enforced. | ||
137 | # (Currently only relevant for ManageSieve) | ||
138 | #sieve_quota_max_storage = 0 | ||
139 | |||
140 | # The primary e-mail address for the user. This is used as a default when no | ||
141 | # other appropriate address is available for sending messages. If this setting | ||
142 | # is not configured, either the postmaster or null "<>" address is used as a | ||
143 | # sender, depending on the action involved. This setting is important when | ||
144 | # there is no message envelope to extract addresses from, such as when the | ||
145 | # script is executed in IMAP. | ||
146 | #sieve_user_email = | ||
147 | |||
148 | # The path to the file where the user log is written. If not configured, a | ||
149 | # default location is used. If the main user's personal Sieve (as configured | ||
150 | # with sieve=) is a file, the logfile is set to <filename>.log by default. If | ||
151 | # it is not a file, the default user log file is ~/.dovecot.sieve.log. | ||
152 | #sieve_user_log = | ||
153 | |||
154 | # Specifies what envelope sender address is used for redirected messages. | ||
155 | # The following values are supported for this setting: | ||
156 | # | ||
157 | # "sender" - The sender address is used (default). | ||
158 | # "recipient" - The final recipient address is used. | ||
159 | # "orig_recipient" - The original recipient is used. | ||
160 | # "user_email" - The user's primary address is used. This is | ||
161 | # configured with the "sieve_user_email" setting. If | ||
162 | # that setting is unconfigured, "user_mail" is equal to | ||
163 | # "recipient". | ||
164 | # "postmaster" - The postmaster_address configured for the LDA. | ||
165 | # "<user@domain>" - Redirected messages are always sent from user@domain. | ||
166 | # The angle brackets are mandatory. The null "<>" address | ||
167 | # is also supported. | ||
168 | # | ||
169 | # This setting is ignored when the envelope sender is "<>". In that case the | ||
170 | # sender of the redirected message is also always "<>". | ||
171 | #sieve_redirect_envelope_from = sender | ||
172 | |||
173 | ## TRACE DEBUGGING | ||
174 | # Trace debugging provides detailed insight in the operations performed by | ||
175 | # the Sieve script. These settings apply to both the LDA Sieve plugin and the | ||
176 | # IMAPSIEVE plugin. | ||
177 | # | ||
178 | # WARNING: On a busy server, this functionality can quickly fill up the trace | ||
179 | # directory with a lot of trace files. Enable this only temporarily and as | ||
180 | # selective as possible. | ||
181 | |||
182 | # The directory where trace files are written. Trace debugging is disabled if | ||
183 | # this setting is not configured or if the directory does not exist. If the | ||
184 | # path is relative or it starts with "~/" it is interpreted relative to the | ||
185 | # current user's home directory. | ||
186 | #sieve_trace_dir = | ||
187 | |||
188 | # The verbosity level of the trace messages. Trace debugging is disabled if | ||
189 | # this setting is not configured. Possible values are: | ||
190 | # | ||
191 | # "actions" - Only print executed action commands, like keep, | ||
192 | # fileinto, reject and redirect. | ||
193 | # "commands" - Print any executed command, excluding test commands. | ||
194 | # "tests" - Print all executed commands and performed tests. | ||
195 | # "matching" - Print all executed commands, performed tests and the | ||
196 | # values matched in those tests. | ||
197 | #sieve_trace_level = | ||
198 | |||
199 | # Enables highly verbose debugging messages that are usually only useful for | ||
200 | # developers. | ||
201 | #sieve_trace_debug = no | ||
202 | |||
203 | # Enables showing byte code addresses in the trace output, rather than only | ||
204 | # the source line numbers. | ||
205 | #sieve_trace_addresses = no | ||
206 | } | ||
diff --git a/dovecot/Makefile b/dovecot/Makefile new file mode 100644 index 0000000..5d80849 --- /dev/null +++ b/dovecot/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | all: | ||
2 | ln -f `pwd`/sieve ~/sieve | ||
diff --git a/dovecot/dovecot.conf b/dovecot/dovecot.conf new file mode 100644 index 0000000..e98b281 --- /dev/null +++ b/dovecot/dovecot.conf | |||
@@ -0,0 +1,34 @@ | |||
1 | listen = * | ||
2 | |||
3 | ssl = required | ||
4 | |||
5 | ssl_cert = </etc/mail/ssl/fullchain.cer | ||
6 | ssl_key = </etc/mail/ssl/mail.topo.tw.key | ||
7 | ssl_dh = </etc/ssl/dh.pem | ||
8 | |||
9 | mail_location = maildir:~/Maildir | ||
10 | |||
11 | passdb { | ||
12 | # This is where you define your password scheme. | ||
13 | # If you have used blowfish it needs to be 'BLF-CRYPT'. | ||
14 | args = scheme=sha512-crypt /etc/mail/passwd | ||
15 | driver = passwd-file | ||
16 | } | ||
17 | |||
18 | userdb { | ||
19 | args = uid=pham gid=pham home=/home/pham | ||
20 | driver = static | ||
21 | } | ||
22 | |||
23 | protocols = imap lmtp | ||
24 | |||
25 | service imap-login { | ||
26 | inet_listener imaps { | ||
27 | port = 993 | ||
28 | ssl = yes | ||
29 | } | ||
30 | # Disable imap | ||
31 | inet_listener imap { | ||
32 | port = 0 | ||
33 | } | ||
34 | } | ||
diff --git a/dovecot/sieve b/dovecot/sieve new file mode 100644 index 0000000..b11f1cc --- /dev/null +++ b/dovecot/sieve | |||
@@ -0,0 +1,149 @@ | |||
1 | # Sieve filter | ||
2 | |||
3 | # Declare the extensions used by this script. | ||
4 | require ["fileinto", "reject", "variables", "editheader"]; | ||
5 | |||
6 | # If transport is not encrypted, add warning emoji at the beginning of the subject | ||
7 | if header :contains "Received" ["by topo.tw (Postfix) with ESMTP "] | ||
8 | { | ||
9 | # Match the entire subject | ||
10 | if header :matches "Subject" "*" { | ||
11 | # Stored in a variable: | ||
12 | set "subject" "${1}"; | ||
13 | } | ||
14 | deleteheader "Subject"; | ||
15 | addheader :last "Subject" "⚠ ${subject}"; | ||
16 | } | ||
17 | |||
18 | # Edit header for test | ||
19 | if header :contains "From" ["typebrook@gmail.com"] { | ||
20 | # Match the entire subject ... | ||
21 | if header :matches "Subject" "*" { | ||
22 | # ... to get it in a match group that can then be stored in a variable: | ||
23 | set "subject" "${1}"; | ||
24 | } | ||
25 | deleteheader "Subject"; | ||
26 | addheader :last "Subject" "Warning: ${subject}"; | ||
27 | } | ||
28 | |||
29 | # CAUTION!! | ||
30 | # Put this block at the top so unwanted mail are discarded | ||
31 | # Message which will trigger commands | ||
32 | # Discard them so we only have message in Sent | ||
33 | if allof ( | ||
34 | address :is ["To"] "mastodon@topo.tw", | ||
35 | header :matches "X-Original-To" "mastodon@topo.tw" | ||
36 | ) { | ||
37 | discard; | ||
38 | } | ||
39 | |||
40 | elsif header :contains "From" [ | ||
41 | "HANCHOR", | ||
42 | "info@members.netflix.com", | ||
43 | "Amazon Web Services", | ||
44 | "no-reply@wamazing.jp", | ||
45 | "info@join.netflix.com", | ||
46 | "noreply@steampowered.com" | ||
47 | ] { | ||
48 | fileinto "promotion"; | ||
49 | } | ||
50 | |||
51 | elsif header :matches :comparator "i;ascii-casemap" "Subject" [ | ||
52 | "*login*", | ||
53 | "*verify*", | ||
54 | "*sign-in*", | ||
55 | "*登入*", | ||
56 | "*密碼*", | ||
57 | "*安全性警示*", | ||
58 | "*new IP Address*" | ||
59 | ] { | ||
60 | fileinto "login"; | ||
61 | } | ||
62 | |||
63 | elsif header :matches :comparator "i;ascii-casemap" "Subject" [ | ||
64 | "*系統公告*" | ||
65 | ] { | ||
66 | fileinto "service"; | ||
67 | } | ||
68 | |||
69 | elsif header :contains :comparator "i;ascii-casemap" "Subject" [ | ||
70 | "帳單", | ||
71 | "付款", | ||
72 | "繳款", | ||
73 | "扣款", | ||
74 | "交易", | ||
75 | "費用", | ||
76 | "eGUI", | ||
77 | "Invoice", | ||
78 | "發票", | ||
79 | "Receipt", | ||
80 | "Billing", | ||
81 | "Expense" | ||
82 | ] { | ||
83 | fileinto "pay"; | ||
84 | } | ||
85 | |||
86 | elsif header :matches :comparator "i;ascii-casemap" "Subject" ["*永豐*"] { | ||
87 | fileinto "STOCK"; | ||
88 | } | ||
89 | |||
90 | elsif address :is ["From"] "no-reply@hackmd.io" { | ||
91 | fileinto "update"; | ||
92 | } | ||
93 | |||
94 | elsif address :is ["From"] "notifications@github.com" { | ||
95 | fileinto "github"; | ||
96 | } | ||
97 | |||
98 | elsif address :contains ["To", "Cc"] "arch-general@lists.archlinux.org" { | ||
99 | fileinto "mailing_list.arch-general"; | ||
100 | } | ||
101 | |||
102 | elsif address :is ["From", "To", "Cc"] "mutt-users@mutt.org" { | ||
103 | fileinto "mailing_list.mutt-users"; | ||
104 | } | ||
105 | |||
106 | elsif address :is ["From", "To", "Cc"] "help-bash@gnu.org" { | ||
107 | fileinto "mailing_list.bash"; | ||
108 | } | ||
109 | |||
110 | elsif header :matches "Sender" "*~rjarry/aerc-discuss@lists.sr.ht*" { | ||
111 | fileinto "mailing_list.aerc"; | ||
112 | } | ||
113 | |||
114 | elsif header :matches "Chat-Version" ["*"] { | ||
115 | fileinto "DeltaChat"; | ||
116 | } | ||
117 | |||
118 | elsif header :matches "X-Original-To" ["cybersec@topo.tw"] { | ||
119 | fileinto "cybersec"; | ||
120 | } | ||
121 | |||
122 | elsif address :is ["To"] "lay9412206@gmail.com" { | ||
123 | fileinto "hometeach"; | ||
124 | } | ||
125 | |||
126 | # Spam Rule: | ||
127 | # Message does not contain my address in "To", "CC" or "BCC" | ||
128 | elsif anyof ( | ||
129 | not header :contains ["To", "Cc", "Bcc", "X-Original-To"] "topo.tw", | ||
130 | header :contains "X-Original-To" "eocuk17" | ||
131 | ) { | ||
132 | fileinto "spam"; | ||
133 | } | ||
134 | # Or fake header in "From" | ||
135 | elsif allof ( | ||
136 | header :matches "From" "*@topo.tw*", | ||
137 | not header :contains "Received" [ | ||
138 | "from topo.tw", | ||
139 | "from PC", | ||
140 | "from [127.0.0.1]", | ||
141 | "by topo.tw" | ||
142 | ] | ||
143 | ) { | ||
144 | fileinto "spam"; | ||
145 | } | ||
146 | |||
147 | else { | ||
148 | fileinto "INBOX"; | ||
149 | } | ||
diff --git a/git/README.md b/git/README.md new file mode 100644 index 0000000..5637f06 --- /dev/null +++ b/git/README.md | |||
@@ -0,0 +1,9 @@ | |||
1 | ## For Git Daemon | ||
2 | |||
3 | read https://git-scm.com/book/be/v2/Git-on-the-Server-Git-Daemon | ||
4 | |||
5 | ## For Http Files for Git | ||
6 | |||
7 | refs: | ||
8 | - https://mtkn.jp/computer/git_server.html | ||
9 | - https://codemadness.org/stagit.html | ||
diff --git a/git/create.sh b/git/create.sh new file mode 100755 index 0000000..f2f4227 --- /dev/null +++ b/git/create.sh | |||
@@ -0,0 +1,53 @@ | |||
1 | #!/bin/bash | ||
2 | # - Makes index for repositories in a single directory. | ||
3 | # - Makes static pages for each repository directory. | ||
4 | # | ||
5 | # NOTE, things to do manually (once) before running this script: | ||
6 | # - copy style.css, logo.png and favicon.png manually, a style.css example | ||
7 | # is included. | ||
8 | # | ||
9 | # - write clone URL, for example "git://git.codemadness.org/dir" to the "url" | ||
10 | # file for each repo. | ||
11 | # - write owner of repo to the "owner" file. | ||
12 | # - write description in "description" file. | ||
13 | # | ||
14 | # Usage: | ||
15 | # - mkdir -p htmldir && cd htmldir | ||
16 | # - sh example_create.sh | ||
17 | |||
18 | ORIG_DIR=`pwd` | ||
19 | |||
20 | # path must be absolute. | ||
21 | reposdir="/srv/git" | ||
22 | curdir="/srv/git/www" | ||
23 | |||
24 | cd ${curdir} | ||
25 | |||
26 | # make files per repo. | ||
27 | for dir in "${reposdir}/"*/; do | ||
28 | # strip .git suffix. | ||
29 | r=$(basename "${dir}") | ||
30 | d=$(basename "${dir}" ".git") | ||
31 | printf "%s... " "${d}" | ||
32 | |||
33 | mkdir -p "${curdir}/${d}" | ||
34 | cd "${curdir}/${d}" || continue | ||
35 | |||
36 | test -f ${dir}/owner || echo `whoami` >${dir}/owner | ||
37 | test -f ${dir}/url || echo git://git.topo.tw/${d} >${dir}/url | ||
38 | |||
39 | stagit -c ".cache" -u "https://git.codemadness.nl/$d/" "${reposdir}/${r}" | ||
40 | |||
41 | # symlinks | ||
42 | ln -sf log.html index.html | ||
43 | ln -sf ../style.css style.css | ||
44 | ln -sf ../logo.png logo.png | ||
45 | ln -sf ../favicon.png favicon.png | ||
46 | |||
47 | echo "done" | ||
48 | done | ||
49 | |||
50 | # make index. | ||
51 | stagit-index "${reposdir}/"*/ > "${curdir}/index.html" | ||
52 | |||
53 | cd ${ORIG_DIR} | ||
diff --git a/git/daemon.sh b/git/daemon.sh new file mode 100755 index 0000000..3cfac1b --- /dev/null +++ b/git/daemon.sh | |||
@@ -0,0 +1,7 @@ | |||
1 | #! /bin/bash | ||
2 | |||
3 | git daemon \ | ||
4 | --export-all \ | ||
5 | --enable=upload-archive \ | ||
6 | --verbose --base-path=`pwd` \ | ||
7 | -- `pwd`/* | ||
diff --git a/git/git-daemon.service b/git/git-daemon.service new file mode 100644 index 0000000..4641aea --- /dev/null +++ b/git/git-daemon.service | |||
@@ -0,0 +1,21 @@ | |||
1 | [Unit] | ||
2 | Description=Start Git Daemon | ||
3 | Requires=network-online.target | ||
4 | After=network-online.target | ||
5 | |||
6 | [Service] | ||
7 | ExecStart=/home/pham/git/vps/git/daemon.sh | ||
8 | WorkingDirectory=/srv/git | ||
9 | |||
10 | Restart=always | ||
11 | RestartSec=500ms | ||
12 | |||
13 | StandardOutput=syslog | ||
14 | StandardError=syslog | ||
15 | SyslogIdentifier=git-daemon | ||
16 | |||
17 | User=pham | ||
18 | Group=pham | ||
19 | |||
20 | [Install] | ||
21 | WantedBy=multi-user.target | ||
diff --git a/nginx/.gitignore b/nginx/.gitignore new file mode 100644 index 0000000..c5d401b --- /dev/null +++ b/nginx/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | src/ | ||
2 | *tar.gz | ||
diff --git a/nginx/Makefile b/nginx/Makefile new file mode 100644 index 0000000..cb995f7 --- /dev/null +++ b/nginx/Makefile | |||
@@ -0,0 +1,28 @@ | |||
1 | .ONESHELL: | ||
2 | |||
3 | VERSION=1.27.2 | ||
4 | |||
5 | all: src /home/pham/git/ngx_http_proxy_connect_module | ||
6 | cd $< | ||
7 | nginx -V |& \ | ||
8 | sed -nE 's/^configure arguments: ([^\n]*)$$/\1/p' | \ | ||
9 | sed -nE 's/([^'"'"' \t\n]+('"'"'([^'"'"'\]|\\'"'"'?)*'"'"'|"([^"\\]|\\"?)*")?) ?/\1\n/gp' | \ | ||
10 | xargs ./configure \ | ||
11 | --with-http_xslt_module=dynamic \ | ||
12 | --with-http_dav_module \ | ||
13 | --with-http_image_filter_module \ | ||
14 | --add-dynamic-module=/home/pham/git/ngx_http_proxy_connect_module | ||
15 | make modules | ||
16 | make | ||
17 | sudo make install | ||
18 | #cd ../.. && rm -rf nginx | ||
19 | |||
20 | src: | ||
21 | curl -O https://nginx.org/download/nginx-${VERSION}.tar.gz | ||
22 | tar zxvf nginx-${VERSION}.tar.gz && mv nginx-${VERSION} $@ | ||
23 | |||
24 | config: | ||
25 | ln -sf `pwd`/* /etc/nginx | ||
26 | |||
27 | /home/pham/git/ngx_http_proxy_connect_module: | ||
28 | git clone https://github.com/chobits/ngx_http_proxy_connect_module $@ | ||
diff --git a/nginx/layout/gal.xslt b/nginx/layout/gal.xslt new file mode 100644 index 0000000..fadcc37 --- /dev/null +++ b/nginx/layout/gal.xslt | |||
@@ -0,0 +1,67 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> | ||
3 | <xsl:output method="html" encoding="utf-8" indent="yes" /> | ||
4 | <xsl:template match="/"> | ||
5 | <xsl:text disable-output-escaping='yes'><!DOCTYPE html></xsl:text> | ||
6 | <html> | ||
7 | <head> | ||
8 | <title><xsl:value-of select="$title" /></title> | ||
9 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
10 | <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css" integrity="sha256-Vzbj7sDDS/woiFS3uNKo8eIuni59rjyNGtXfstRzStA=" crossorigin="anonymous"/> | ||
11 | <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script> | ||
12 | <script src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js" integrity="sha256-yt2kYMy0w8AbtF89WXb2P1rfjcP/HTHLT7097U8Y5b8=" crossorigin="anonymous"></script> | ||
13 | <script src="https://cdn.jsdelivr.net/npm/jszip@3.1.5/dist/jszip.min.js" integrity="sha256-PZ/OvdXxEW1u3nuTAUCSjd4lyaoJ3UJpv/X11x2Gi5c=" crossorigin="anonymous"></script> | ||
14 | <script src="https://cdn.jsdelivr.net/npm/file-saver@2.0.5/dist/FileSaver.min.js" integrity="sha256-xoh0y6ov0WULfXcLMoaA6nZfszdgI8w2CEJ/3k8NBIE=" crossorigin="anonymous"></script> | ||
15 | <style>img { display: block; }</style> | ||
16 | </head> | ||
17 | <body> | ||
18 | <h1 style="text-align: center;"><xsl:value-of select="$title"/></h1> | ||
19 | <div style="border-bottom: 1px solid gray; margin-bottom: 1rem;"></div> | ||
20 | <div style="display: flex; flex-wrap: wrap; gap: 2px; justify-content: center;"> | ||
21 | <xsl:for-each select="list/file"> | ||
22 | <xsl:sort order="descending"/> | ||
23 | <a href="{.}" data-fancybox="gallery"> | ||
24 | <img loading="lazy" src="{.}!lg" height="200"/> | ||
25 | </a> | ||
26 | </xsl:for-each> | ||
27 | </div> | ||
28 | <script> | ||
29 | async function downloadAll() { | ||
30 | const zip = JSZip(); | ||
31 | const folder = zip.folder('<xsl:value-of select="$title" />'); | ||
32 | const files = [ | ||
33 | <xsl:for-each select="list/file"> | ||
34 | <xsl:value-of select="." /> | ||
35 | </xsl:for-each> | ||
36 | ]; | ||
37 | for(const i in files) { | ||
38 | const file = files[i]; | ||
39 | const resp = await fetch(file); | ||
40 | folder.file(file, resp.blob()); | ||
41 | $.fancybox.animate($.fancybox.getInstance().SlideShow.$progress.show(),{scaleX: i/files.length}, 0.1); | ||
42 | } | ||
43 | const zipFile = await zip.generateAsync({type: 'blob'}); | ||
44 | saveAs(zipFile, '<xsl:value-of select="$title" />' + '.zip'); | ||
45 | $.fancybox.animate($.fancybox.getInstance().SlideShow.$progress.show(),{scaleX: 0}, 0.1); | ||
46 | } | ||
47 | |||
48 | $('[data-fancybox="gallery"]').fancybox({ | ||
49 | buttons: [ | ||
50 | "thumbs", | ||
51 | "slideShow", | ||
52 | "fullScreen", | ||
53 | "downloadAll", | ||
54 | "close" | ||
55 | ], | ||
56 | btnTpl: { | ||
57 | downloadAll: | ||
58 | '<a class="fancybox-button fancybox-button--download" title="Download All" href="javascript:downloadAll()">' + | ||
59 | '<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3M3 17V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z" style="fill:unset; stroke-width:2"/></svg>' + | ||
60 | '</a>', | ||
61 | } | ||
62 | }); | ||
63 | </script> | ||
64 | </body> | ||
65 | </html> | ||
66 | </xsl:template> | ||
67 | </xsl:stylesheet> | ||
diff --git a/nginx/layout/simple-gal.xslt b/nginx/layout/simple-gal.xslt new file mode 100644 index 0000000..749be72 --- /dev/null +++ b/nginx/layout/simple-gal.xslt | |||
@@ -0,0 +1,36 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> | ||
3 | <xsl:output method="html" encoding="utf-8" indent="yes" /> | ||
4 | <xsl:template match="/"> | ||
5 | <xsl:text disable-output-escaping='yes'><!DOCTYPE html></xsl:text> | ||
6 | <html> | ||
7 | <head> | ||
8 | <title><xsl:value-of select="$title" /></title> | ||
9 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
10 | <style> | ||
11 | img { | ||
12 | display: inline; | ||
13 | width: 23%; | ||
14 | margin: 2mm; | ||
15 | vertical-align: bottom; | ||
16 | } | ||
17 | @media all and (max-width: 20.4cm) { | ||
18 | img { | ||
19 | max-width: calc(100% - 4mm); | ||
20 | } | ||
21 | } | ||
22 | body { | ||
23 | margin: 0; | ||
24 | } | ||
25 | </style> | ||
26 | </head> | ||
27 | <body> | ||
28 | <xsl:for-each select="list/file"> | ||
29 | <a href="{.}" title="click to enlarge"> | ||
30 | <img src="{.}" alt="{.}"/> | ||
31 | </a> | ||
32 | </xsl:for-each> | ||
33 | </body> | ||
34 | </html> | ||
35 | </xsl:template> | ||
36 | </xsl:stylesheet> | ||
diff --git a/nginx/layout/simple.xslt b/nginx/layout/simple.xslt new file mode 100644 index 0000000..9cc5ad6 --- /dev/null +++ b/nginx/layout/simple.xslt | |||
@@ -0,0 +1,51 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> | ||
3 | <xsl:template match="/"> | ||
4 | <html> | ||
5 | <body style="margin: 0 auto; max-width: 900px; width: fit-content;"> | ||
6 | |||
7 | <h3><xsl:value-of select="name(//directory)"/></h3> | ||
8 | |||
9 | <table border="0"> | ||
10 | <tr bgcolor="#7DAFFF"> | ||
11 | <th>Name</th> | ||
12 | <th style="padding-inline: 2em;">Size</th> | ||
13 | <th>Date</th> | ||
14 | </tr> | ||
15 | <xsl:for-each select="list/*"> | ||
16 | <xsl:sort select="mtime" /> | ||
17 | |||
18 | <xsl:variable name="name"> | ||
19 | <xsl:value-of select="."/> | ||
20 | </xsl:variable> | ||
21 | |||
22 | <xsl:variable name="size"> | ||
23 | <xsl:if test="string-length(@size) > 0"> | ||
24 | <xsl:if test="number(@size) > 0"> | ||
25 | <xsl:choose> | ||
26 | <xsl:when test="round(@size div 1024) < 1"><xsl:value-of select="@size" /></xsl:when> | ||
27 | <xsl:when test="round(@size div 1048576) < 1"><xsl:value-of select="format-number((@size div 1024), '0.0')" />K</xsl:when> | ||
28 | <xsl:otherwise><xsl:value-of select="format-number((@size div 1048576), '0.00')" /> MB</xsl:otherwise> | ||
29 | </xsl:choose> | ||
30 | </xsl:if> | ||
31 | </xsl:if> | ||
32 | </xsl:variable> | ||
33 | |||
34 | <xsl:variable name="date"> | ||
35 | <xsl:value-of select="substring(@mtime,6,2)"/>/<xsl:value-of select="substring(@mtime,9,2)"/><xsl:text> </xsl:text> | ||
36 | <xsl:value-of select="substring(@mtime,12,2)"/>:<xsl:value-of select="substring(@mtime,15,2)"/>:<xsl:value-of select="substring(@mtime,18,2)"/><xsl:text> </xsl:text> | ||
37 | <xsl:value-of select="substring(@mtime,1,4)"/> | ||
38 | </xsl:variable> | ||
39 | |||
40 | <tr> | ||
41 | <td><a href="{$name}"><xsl:value-of select="."/></a></td> | ||
42 | <td align="right" style="padding-right: 2em;"><xsl:value-of select="$size"/></td> | ||
43 | <td><xsl:value-of select="$date"/></td> | ||
44 | </tr> | ||
45 | |||
46 | </xsl:for-each> | ||
47 | </table> | ||
48 | </body> | ||
49 | </html> | ||
50 | </xsl:template> | ||
51 | </xsl:stylesheet> | ||
diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..d0601ec --- /dev/null +++ b/nginx/nginx.conf | |||
@@ -0,0 +1,131 @@ | |||
1 | load_module /etc/nginx/modules/ngx_http_dav_ext_module.so; | ||
2 | load_module /etc/nginx/modules/ngx_http_xslt_filter_module.so; | ||
3 | load_module /etc/nginx/modules/ngx_http_proxy_connect_module.so; | ||
4 | |||
5 | user pham; | ||
6 | worker_processes 1; | ||
7 | |||
8 | #error_log logs/error.log; | ||
9 | #error_log logs/error.log notice; | ||
10 | #error_log logs/error.log info; | ||
11 | |||
12 | #pid logs/nginx.pid; | ||
13 | |||
14 | |||
15 | events { | ||
16 | worker_connections 1024; | ||
17 | } | ||
18 | |||
19 | |||
20 | http { | ||
21 | types_hash_max_size 4096; | ||
22 | server_names_hash_bucket_size 128; | ||
23 | |||
24 | include mime.types; | ||
25 | default_type application/octet-stream; | ||
26 | disable_symlinks off; | ||
27 | |||
28 | # Read manual for valid variables: | ||
29 | # https://nginx.org/en/docs/http/ngx_http_core_module.html#variables | ||
30 | |||
31 | #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' | ||
32 | # '$status $body_bytes_sent "$http_referer" ' | ||
33 | # '"$http_user_agent" "$http_x_forwarded_for"'; | ||
34 | log_format main '$status $request_method\t$http_host$uri\tfrom $http_referer\n' | ||
35 | '$time_iso8601 $remote_addr\r\t\t\t\t\t $http_user_agent'; | ||
36 | access_log /var/log/nginx/access.log main; | ||
37 | |||
38 | sendfile on; | ||
39 | #tcp_nopush on; | ||
40 | |||
41 | #keepalive_timeout 0; | ||
42 | keepalive_timeout 65; | ||
43 | |||
44 | #gzip on; | ||
45 | |||
46 | #server { | ||
47 | # listen 80; | ||
48 | # server_name localhost; | ||
49 | |||
50 | # #charset koi8-r; | ||
51 | |||
52 | # #access_log logs/host.access.log main; | ||
53 | |||
54 | # location / { | ||
55 | # root /usr/share/nginx/html; | ||
56 | # index index.html index.htm; | ||
57 | # } | ||
58 | |||
59 | # #error_page 404 /404.html; | ||
60 | |||
61 | # # redirect server error pages to the static page /50x.html | ||
62 | # # | ||
63 | # error_page 500 502 503 504 /50x.html; | ||
64 | # location = /50x.html { | ||
65 | # root /usr/share/nginx/html; | ||
66 | # } | ||
67 | |||
68 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 | ||
69 | # | ||
70 | #location ~ \.php$ { | ||
71 | # proxy_pass http://127.0.0.1; | ||
72 | #} | ||
73 | |||
74 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 | ||
75 | # | ||
76 | #location ~ \.php$ { | ||
77 | # root html; | ||
78 | # fastcgi_pass 127.0.0.1:9000; | ||
79 | # fastcgi_index index.php; | ||
80 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; | ||
81 | # include fastcgi_params; | ||
82 | #} | ||
83 | |||
84 | # deny access to .htaccess files, if Apache's document root | ||
85 | # concurs with nginx's one | ||
86 | # | ||
87 | #location ~ /\.ht { | ||
88 | # deny all; | ||
89 | #} | ||
90 | #} | ||
91 | |||
92 | |||
93 | # another virtual host using mix of IP-, name-, and port-based configuration | ||
94 | # | ||
95 | #server { | ||
96 | # listen 8000; | ||
97 | # listen somename:8080; | ||
98 | # server_name somename alias another.alias; | ||
99 | |||
100 | # location / { | ||
101 | # root html; | ||
102 | # index index.html index.htm; | ||
103 | # } | ||
104 | #} | ||
105 | |||
106 | |||
107 | # HTTPS server | ||
108 | # | ||
109 | #server { | ||
110 | # listen 443 ssl; | ||
111 | # server_name localhost; | ||
112 | |||
113 | # ssl_certificate cert.pem; | ||
114 | # ssl_certificate_key cert.key; | ||
115 | |||
116 | # ssl_session_cache shared:SSL:1m; | ||
117 | # ssl_session_timeout 5m; | ||
118 | |||
119 | # ssl_ciphers HIGH:!aNULL:!MD5; | ||
120 | # ssl_prefer_server_ciphers on; | ||
121 | |||
122 | # location / { | ||
123 | # root html; | ||
124 | # index index.html index.htm; | ||
125 | # } | ||
126 | #} | ||
127 | |||
128 | # load configs | ||
129 | #include /etc/nginx/conf.d/*.conf; | ||
130 | include /etc/nginx/sites-enabled/vps; | ||
131 | } | ||
diff --git a/nginx/passwd/2022.10.11 b/nginx/passwd/2022.10.11 new file mode 100644 index 0000000..7037748 --- /dev/null +++ b/nginx/passwd/2022.10.11 | |||
@@ -0,0 +1 @@ | |||
lay911225:$apr1$yc365c.t$HrUOy9eWekr6xNkWsTZBR. | |||
diff --git a/nginx/passwd/houshou b/nginx/passwd/houshou new file mode 100644 index 0000000..7ec2d1d --- /dev/null +++ b/nginx/passwd/houshou | |||
@@ -0,0 +1 @@ | |||
houshou:$apr1$tSspURxF$zciiExFt0nj0n.pbJiXUh0 | |||
diff --git a/nginx/passwd/japan b/nginx/passwd/japan new file mode 100644 index 0000000..da8a465 --- /dev/null +++ b/nginx/passwd/japan | |||
@@ -0,0 +1 @@ | |||
klara:$apr1$ZCAf5ib0$ZjDi7s1djpikGXhRQaQX01 | |||
diff --git a/nginx/passwd/ntumountainclub b/nginx/passwd/ntumountainclub new file mode 100644 index 0000000..d485239 --- /dev/null +++ b/nginx/passwd/ntumountainclub | |||
@@ -0,0 +1 @@ | |||
radio:$apr1$rexQL6MJ$MRLWfUmi4FyeJ65oKYz/Q/ | |||
diff --git a/nginx/passwd/rescue b/nginx/passwd/rescue new file mode 100644 index 0000000..d46bf6f --- /dev/null +++ b/nginx/passwd/rescue | |||
@@ -0,0 +1 @@ | |||
mountainclub:$apr1$H5RdWRmY$Clj3PkR.x4vLomKNK/ZN3. | |||
diff --git a/nginx/sites-available/vps b/nginx/sites-available/vps new file mode 100644 index 0000000..bad4621 --- /dev/null +++ b/nginx/sites-available/vps | |||
@@ -0,0 +1,354 @@ | |||
1 | #map $token $api_client_name { | ||
2 | # default ""; | ||
3 | # | ||
4 | # # CAUTION!! Change token and client name wisely | ||
5 | # "XXXX" "client"; | ||
6 | #} | ||
7 | |||
8 | # Gets the basename of the original request | ||
9 | map $request_uri $request_basename { | ||
10 | ~/(?<captured_request_basename>[^/?]*)(?:\?|$) $captured_request_basename; | ||
11 | } | ||
12 | |||
13 | # Gets the basename of the current uri | ||
14 | map $uri $basename { | ||
15 | ~/(?<captured_basename>[^/]*)$ $captured_basename; | ||
16 | } | ||
17 | |||
18 | server { | ||
19 | server_name topo.tw www.topo.tw; | ||
20 | |||
21 | listen 80; | ||
22 | listen 443 ssl; | ||
23 | ssl_certificate /etc/nginx/ssl/fullchain.cert; | ||
24 | ssl_certificate_key /etc/nginx/ssl/cert.pem; | ||
25 | |||
26 | root /srv/http; | ||
27 | index index.html; | ||
28 | autoindex on; | ||
29 | autoindex_exact_size off; | ||
30 | |||
31 | # charset | ||
32 | charset utf-8; | ||
33 | charset_types *; | ||
34 | override_charset on; | ||
35 | default_type "text/plain; charset=utf-8"; | ||
36 | |||
37 | # header | ||
38 | proxy_set_header Host $host; | ||
39 | add_header Cache-Control "no-cache" always; | ||
40 | #add_header Cache-Control "max-age=604800"; | ||
41 | error_page 404 /404.html; | ||
42 | error_log /var/log/nginx/error.log debug; | ||
43 | #rewrite_log on; | ||
44 | |||
45 | location ~ \.html$ { | ||
46 | try_files $uri =404; | ||
47 | } | ||
48 | |||
49 | location ~ \.js$ { | ||
50 | add_header Access-Control-Allow-Origin *; | ||
51 | } | ||
52 | |||
53 | location ~ [^/]$ { | ||
54 | try_files $uri @rewrite_no_slash; | ||
55 | } | ||
56 | |||
57 | location @rewrite_no_slash { | ||
58 | add_header rewrite no_slash; | ||
59 | rewrite ^(.+)$ $1.html permanent; | ||
60 | } | ||
61 | |||
62 | location ~ /$ { | ||
63 | try_files $uri @rewrite_slash; | ||
64 | } | ||
65 | |||
66 | location @rewrite_slash { | ||
67 | rewrite ^(.+)/$ $1.html permanent; | ||
68 | } | ||
69 | |||
70 | rewrite ^/posts$ /posts/ permanent; | ||
71 | location = /posts/ { | ||
72 | autoindex_format xml; | ||
73 | xslt_string_param title "/posts/"; | ||
74 | xslt_stylesheet layout/simple.xslt; | ||
75 | add_header Cache-Control "no-cache" always; | ||
76 | } | ||
77 | |||
78 | # This configuration allow you to upload/modify/delete file, for example: | ||
79 | # curl -X PUT -F file=@foo https://topo.tw/doc/bar | ||
80 | location ^~ /doc { | ||
81 | alias /home/pham/doc/; | ||
82 | |||
83 | client_body_temp_path /tmp/client_temp; | ||
84 | dav_methods PUT DELETE MKCOL COPY MOVE; | ||
85 | create_full_put_path on; | ||
86 | dav_access group:rw all:r; | ||
87 | client_max_body_size 10000m; | ||
88 | } | ||
89 | |||
90 | location ^~ /photos/ { | ||
91 | alias /home/pham/data/s3.photos/; | ||
92 | autoindex_format xml; | ||
93 | xslt_string_param title "photos"; | ||
94 | xslt_stylesheet layout/gal.xslt; | ||
95 | try_files $uri $uri/ =404; | ||
96 | expires max; | ||
97 | |||
98 | if ($uri ~ ^/photos/([^!]+)!(large|lg|md)$ ) { | ||
99 | set $filename /home/pham/data/s3.photos/$1; | ||
100 | set $img_version $2; | ||
101 | rewrite ^ /thumbnail; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | rewrite ^/p(ublic)?$ /public/ permanent; | ||
106 | rewrite ^/p/(.*)$ /public/$1; | ||
107 | location ^~ /public/ { | ||
108 | alias /home/pham/public/; | ||
109 | autoindex_format xml; | ||
110 | xslt_string_param title "/posts/"; | ||
111 | xslt_stylesheet layout/simple.xslt; | ||
112 | add_header Access-Control-Allow-Origin "*" always; | ||
113 | add_header Cache-Control "no-cache" always; | ||
114 | } | ||
115 | |||
116 | # thumbnail CGI, requires variables 'filename' and 'img_version' | ||
117 | location = /thumbnail { | ||
118 | # Prepare the required parameters (width, height, cropping or zooming) according to the URL address! | ||
119 | set $img_type resize; | ||
120 | set $img_w -; | ||
121 | set $img_h -; | ||
122 | if ($img_version = 'large') { | ||
123 | set $img_type resize; | ||
124 | set $img_w 1920; | ||
125 | } | ||
126 | if ($img_version = 'lg') { | ||
127 | set $img_type crop; | ||
128 | set $img_w 256; | ||
129 | set $img_h 256; | ||
130 | } | ||
131 | if ($img_version = 'md') { | ||
132 | set $img_type crop; | ||
133 | set $img_w 128; | ||
134 | set $img_h 128; | ||
135 | } | ||
136 | rewrite ^ /_$img_type; | ||
137 | } | ||
138 | |||
139 | # Processing of Scaled Pictures | ||
140 | location = /_resize { | ||
141 | alias $filename; | ||
142 | image_filter resize $img_w $img_h; | ||
143 | image_filter_jpeg_quality 95; | ||
144 | image_filter_buffer 20M; | ||
145 | image_filter_interlace on; | ||
146 | } | ||
147 | |||
148 | # Processing of clipped pictures | ||
149 | location = /_crop { | ||
150 | alias $filename; | ||
151 | image_filter crop $img_w $img_h; | ||
152 | image_filter_jpeg_quality 95; | ||
153 | image_filter_buffer 20M; | ||
154 | image_filter_interlace on; | ||
155 | } | ||
156 | |||
157 | location ^~ /wallpapers { | ||
158 | alias /home/pham/public/wallpapers/; | ||
159 | |||
160 | autoindex_format xml; | ||
161 | xslt_string_param title "Wallpaper Collection!"; | ||
162 | xslt_stylesheet layout/gal.xslt; | ||
163 | try_files $uri $uri/ =404; | ||
164 | |||
165 | if ($uri ~ ([^/!]+)!(large|lg|md)$ ) { | ||
166 | set $filename /home/pham/public/wallpapers/$1; | ||
167 | set $img_version $2; | ||
168 | rewrite ^ /thumbnail; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | location ^~ /tmp { | ||
173 | alias /home/pham/public/tmp/; | ||
174 | autoindex on; | ||
175 | add_header "Content-Type" "text/plain; charset=utf-8"; | ||
176 | } | ||
177 | |||
178 | location ^~ /osm { | ||
179 | alias /home/pham/public/osm/; | ||
180 | autoindex on; | ||
181 | } | ||
182 | |||
183 | location ^~ /tainan/ { | ||
184 | alias /home/pham/public/tainan/; | ||
185 | autoindex on; | ||
186 | index =404; | ||
187 | } | ||
188 | |||
189 | location /public/layx { | ||
190 | alias /home/pham/public/layx/; | ||
191 | |||
192 | autoindex on; | ||
193 | |||
194 | auth_basic "You need to login"; | ||
195 | auth_basic_user_file /etc/nginx/passwd/2022.10.11; | ||
196 | } | ||
197 | |||
198 | location ^~ /private/ { | ||
199 | alias /home/pham/private/; | ||
200 | autoindex on; | ||
201 | auth_basic "You need to login"; | ||
202 | auth_basic_user_file /etc/nginx/passwd/japan; | ||
203 | } | ||
204 | |||
205 | location = /japan.html { | ||
206 | autoindex on; | ||
207 | |||
208 | auth_basic "You need to login"; | ||
209 | auth_basic_user_file /etc/nginx/passwd/japan; | ||
210 | } | ||
211 | |||
212 | location ^~ /houshou { | ||
213 | alias /home/pham/houshou/; | ||
214 | |||
215 | autoindex on; | ||
216 | autoindex_format xml; | ||
217 | xslt_string_param title "Houshou Collection!"; | ||
218 | xslt_stylesheet layout/gal.xslt; | ||
219 | try_files $uri $uri/ =404; | ||
220 | |||
221 | auth_basic "You need to login"; | ||
222 | auth_basic_user_file /etc/nginx/passwd/houshou; | ||
223 | |||
224 | if ($uri ~ ([^/!]+)!(large|lg|md)$ ) { | ||
225 | set $filename /home/pham/houshou/$1; | ||
226 | set $img_version $2; | ||
227 | rewrite ^ /thumbnail; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | location ^~ /houshou2 { | ||
232 | alias /home/pham/houshou2/; | ||
233 | |||
234 | autoindex on; | ||
235 | autoindex_format xml; | ||
236 | xslt_string_param title "Houshou Collection!"; | ||
237 | #xslt_stylesheet layout/simple-gal.xslt; | ||
238 | xslt_stylesheet layout/gal.xslt; | ||
239 | try_files $uri $uri/ =404; | ||
240 | |||
241 | if ($uri ~ ([^/!]+)!(large|lg|md)$ ) { | ||
242 | set $filename /home/pham/houshou2/$1; | ||
243 | set $img_version $2; | ||
244 | rewrite ^ /thumbnail; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | location /rescue { | ||
249 | root /home/pham; | ||
250 | |||
251 | auth_basic "You need to login"; | ||
252 | auth_basic_user_file /etc/nginx/passwd/rescue; | ||
253 | } | ||
254 | |||
255 | # location /upload/ { | ||
256 | # proxy_pass http://127.0.0.1:8000/; | ||
257 | # } | ||
258 | |||
259 | #rewrite ^/up$ /up/; | ||
260 | #location /up/ { | ||
261 | # proxy_set_header X-Forwarded-Proto https; | ||
262 | # proxy_set_header Referer $host/up/; | ||
263 | # proxy_pass http://127.0.0.1:8080/; | ||
264 | |||
265 | # client_max_body_size 1g; | ||
266 | #} | ||
267 | |||
268 | #location = /_validate_token { | ||
269 | # internal; | ||
270 | |||
271 | # if ($token = "") { | ||
272 | # return 401; # Unauthorized | ||
273 | # } | ||
274 | |||
275 | # if ($api_client_name = "") { | ||
276 | # return 403; # Forbidden | ||
277 | # } | ||
278 | |||
279 | # return 204; # OK (no content) | ||
280 | #} | ||
281 | |||
282 | } | ||
283 | |||
284 | # git server | ||
285 | server { | ||
286 | server_name git.topo.tw; | ||
287 | |||
288 | listen 80; | ||
289 | listen 443 ssl; | ||
290 | ssl_certificate /etc/nginx/ssl/git.topo.tw/fullchain.cer; | ||
291 | ssl_certificate_key /etc/nginx/ssl/git.topo.tw/git.topo.tw.key; | ||
292 | |||
293 | root /srv/git/www; | ||
294 | |||
295 | location ~ (/.*) { | ||
296 | #include fastcgi_params; | ||
297 | #fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend; | ||
298 | ## export all repositories under GIT_PROJECT_ROOT | ||
299 | #fastcgi_param GIT_HTTP_EXPORT_ALL ""; | ||
300 | #fastcgi_param GIT_PROJECT_ROOT /srv/git; | ||
301 | #fastcgi_param PATH_INFO $1; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | # Block all direct accesses via IP address | ||
306 | server { | ||
307 | server_name "~[\d\.]+"; | ||
308 | listen 80; | ||
309 | listen 443 ssl; | ||
310 | |||
311 | error_page 404 /404.html; | ||
312 | return 404; | ||
313 | } | ||
314 | |||
315 | ## Redirect 80 to 443 | ||
316 | #server { | ||
317 | # if ($host = topo.tw) { | ||
318 | # return 301 https://$host$request_uri; | ||
319 | # } # managed by Certbot | ||
320 | # | ||
321 | # | ||
322 | # #listen 80; | ||
323 | # server_name topo.tw; | ||
324 | # return 301 https://$host$request_uri; | ||
325 | # | ||
326 | # | ||
327 | #} | ||
328 | |||
329 | ## Forward Proxy | ||
330 | #server { | ||
331 | # resolver 8.8.8.8; | ||
332 | # listen 13288; | ||
333 | # | ||
334 | # proxy_connect; | ||
335 | # proxy_connect_allow 443 563; | ||
336 | # proxy_connect_connect_timeout 10s; | ||
337 | # proxy_connect_read_timeout 10s; | ||
338 | # proxy_connect_send_timeout 10s; | ||
339 | # location / { | ||
340 | # proxy_pass http://$host; | ||
341 | # proxy_set_header Host $host; | ||
342 | # } | ||
343 | #} | ||
344 | |||
345 | #server { | ||
346 | # server_name demo.topo.tw; | ||
347 | # root /; | ||
348 | # | ||
349 | # location / { | ||
350 | # index /home/pham/git/vps/demo/client.sh; | ||
351 | # add_header Content-Type text/plain; | ||
352 | # } | ||
353 | # #listen 80; | ||
354 | #} | ||
diff --git a/postfix/Makefile b/postfix/Makefile new file mode 100644 index 0000000..f808d21 --- /dev/null +++ b/postfix/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | .ONESHELL: | ||
2 | SHELL := bash | ||
3 | |||
4 | config: | ||
5 | shopt -s extglob | ||
6 | ln -sf `pwd`/!(opendkim) /etc/postfix | ||
7 | mkdir -p /etc/opendkim/ | ||
8 | cp `pwd`/opendkim/* /etc/opendkim/ | ||
9 | chown opendkim:opendkim /etc/opendkim/* | ||
diff --git a/postfix/aliases b/postfix/aliases new file mode 100644 index 0000000..04a104f --- /dev/null +++ b/postfix/aliases | |||
@@ -0,0 +1,268 @@ | |||
1 | # | ||
2 | # Sample aliases file. Install in the location as specified by the | ||
3 | # output from the command "postconf alias_maps". Typical path names | ||
4 | # are /etc/aliases or /etc/mail/aliases. | ||
5 | # | ||
6 | # >>>>>>>>>> The program "newaliases" must be run after | ||
7 | # >> NOTE >> this file is updated for any changes to | ||
8 | # >>>>>>>>>> show through to Postfix. | ||
9 | # | ||
10 | pham: pham | ||
11 | |||
12 | # Person who should get root's mail. Don't receive mail as root! | ||
13 | root: pham | ||
14 | |||
15 | # Basic system aliases -- these MUST be present | ||
16 | MAILER-DAEMON: postmaster | ||
17 | postmaster: pham | ||
18 | |||
19 | # General redirections for pseudo accounts | ||
20 | bin: pham | ||
21 | daemon: pham | ||
22 | named: pham | ||
23 | nobody: pham | ||
24 | uucp: pham | ||
25 | www: pham | ||
26 | ftp-bugs: pham | ||
27 | postfix: pham | ||
28 | |||
29 | # Put your local aliases here. | ||
30 | |||
31 | # Well-known aliases | ||
32 | manager: pham | ||
33 | dumper: pham | ||
34 | operator: pham | ||
35 | abuse: postmaster | ||
36 | |||
37 | # trap decode to catch security attacks | ||
38 | decode: pham | ||
39 | |||
40 | # custom | ||
41 | devnull: /dev/null | ||
42 | |||
43 | # ALIASES(5) ALIASES(5) | ||
44 | # | ||
45 | # NAME | ||
46 | # aliases - Postfix local alias database format | ||
47 | # | ||
48 | # SYNOPSIS | ||
49 | # newaliases | ||
50 | # | ||
51 | # DESCRIPTION | ||
52 | # The aliases(5) table provides a system-wide mechanism to | ||
53 | # redirect mail for local recipients. The redirections are | ||
54 | # processed by the Postfix local(8) delivery agent. | ||
55 | # | ||
56 | # Normally, the aliases(5) table is specified as a text file | ||
57 | # that serves as input to the postalias(1) command. The | ||
58 | # result, an indexed file in dbm or db format, is used for | ||
59 | # fast lookup by the mail system. Execute the command | ||
60 | # newaliases in order to rebuild the indexed file after | ||
61 | # changing the Postfix alias database. | ||
62 | # | ||
63 | # When the table is provided via other means such as NIS, | ||
64 | # LDAP or SQL, the same lookups are done as for ordinary | ||
65 | # indexed files. | ||
66 | # | ||
67 | # Alternatively, the table can be provided as a regu- | ||
68 | # lar-expression map where patterns are given as regular | ||
69 | # expressions. In this case, the lookups are done in a | ||
70 | # slightly different way as described below under "REGULAR | ||
71 | # EXPRESSION TABLES". | ||
72 | # | ||
73 | # Users can control delivery of their own mail by setting up | ||
74 | # .forward files in their home directory. Lines in per-user | ||
75 | # .forward files have the same syntax as the right-hand side | ||
76 | # of aliases(5) entries. | ||
77 | # | ||
78 | # The format of the alias database input file is as follows: | ||
79 | # | ||
80 | # o An alias definition has the form | ||
81 | # | ||
82 | # name: value1, value2, ... | ||
83 | # | ||
84 | # o Empty lines and whitespace-only lines are ignored, | ||
85 | # as are lines whose first non-whitespace character | ||
86 | # is a `#'. | ||
87 | # | ||
88 | # o A logical line starts with non-whitespace text. A | ||
89 | # line that starts with whitespace continues a logi- | ||
90 | # cal line. | ||
91 | # | ||
92 | # The name is a local address (no domain part). Use double | ||
93 | # quotes when the name contains any special characters such | ||
94 | # as whitespace, `#', `:', or `@'. The name is folded to | ||
95 | # lowercase, in order to make database lookups case insensi- | ||
96 | # tive. | ||
97 | # | ||
98 | # In addition, when an alias exists for owner-name, this | ||
99 | # will override the envelope sender address, so that deliv- | ||
100 | # ery diagnostics are directed to owner-name, instead of the | ||
101 | # originator of the message (for details, see | ||
102 | # owner_request_special, expand_owner_alias and | ||
103 | # reset_owner_alias). This is typically used to direct | ||
104 | # delivery errors to the maintainer of a mailing list, who | ||
105 | # is in a better position to deal with mailing list delivery | ||
106 | # problems than the originator of the undelivered mail. | ||
107 | # | ||
108 | # The value contains one or more of the following: | ||
109 | # | ||
110 | # address | ||
111 | # Mail is forwarded to address, which is compatible | ||
112 | # with the RFC 822 standard. | ||
113 | # | ||
114 | # /file/name | ||
115 | # Mail is appended to /file/name. See local(8) for | ||
116 | # details of delivery to file. Delivery is not lim- | ||
117 | # ited to regular files. For example, to dispose of | ||
118 | # unwanted mail, deflect it to /dev/null. | ||
119 | # | ||
120 | # |command | ||
121 | # Mail is piped into command. Commands that contain | ||
122 | # special characters, such as whitespace, should be | ||
123 | # enclosed between double quotes. See local(8) for | ||
124 | # details of delivery to command. | ||
125 | # | ||
126 | # When the command fails, a limited amount of command | ||
127 | # output is mailed back to the sender. The file | ||
128 | # /usr/include/sysexits.h defines the expected exit | ||
129 | # status codes. For example, use "|exit 67" to simu- | ||
130 | # late a "user unknown" error, and "|exit 0" to | ||
131 | # implement an expensive black hole. | ||
132 | # | ||
133 | # :include:/file/name | ||
134 | # Mail is sent to the destinations listed in the | ||
135 | # named file. Lines in :include: files have the same | ||
136 | # syntax as the right-hand side of alias entries. | ||
137 | # | ||
138 | # A destination can be any destination that is | ||
139 | # described in this manual page. However, delivery to | ||
140 | # "|command" and /file/name is disallowed by default. | ||
141 | # To enable, edit the allow_mail_to_commands and | ||
142 | # allow_mail_to_files configuration parameters. | ||
143 | # | ||
144 | # ADDRESS EXTENSION | ||
145 | # When alias database search fails, and the recipient local- | ||
146 | # part contains the optional recipient delimiter (e.g., | ||
147 | # user+foo), the search is repeated for the unextended | ||
148 | # address (e.g., user). | ||
149 | # | ||
150 | # The propagate_unmatched_extensions parameter controls | ||
151 | # whether an unmatched address extension (+foo) is propa- | ||
152 | # gated to the result of table lookup. | ||
153 | # | ||
154 | # CASE FOLDING | ||
155 | # The local(8) delivery agent always folds the search string | ||
156 | # to lowercase before database lookup. | ||
157 | # | ||
158 | # REGULAR EXPRESSION TABLES | ||
159 | # This section describes how the table lookups change when | ||
160 | # the table is given in the form of regular expressions. For | ||
161 | # a description of regular expression lookup table syntax, | ||
162 | # see regexp_table(5) or pcre_table(5). NOTE: these formats | ||
163 | # do not use ":" at the end of a pattern. | ||
164 | # | ||
165 | # Each regular expression is applied to the entire search | ||
166 | # string. Thus, a search string user+foo is not broken up | ||
167 | # into user and foo. | ||
168 | # | ||
169 | # Regular expressions are applied in the order as specified | ||
170 | # in the table, until a regular expression is found that | ||
171 | # matches the search string. | ||
172 | # | ||
173 | # Lookup results are the same as with indexed file lookups. | ||
174 | # For security reasons there is no support for $1, $2 etc. | ||
175 | # substring interpolation. | ||
176 | # | ||
177 | # SECURITY | ||
178 | # The local(8) delivery agent disallows regular expression | ||
179 | # substitution of $1 etc. in alias_maps, because that would | ||
180 | # open a security hole. | ||
181 | # | ||
182 | # The local(8) delivery agent will silently ignore requests | ||
183 | # to use the proxymap(8) server within alias_maps. Instead | ||
184 | # it will open the table directly. Before Postfix version | ||
185 | # 2.2, the local(8) delivery agent will terminate with a | ||
186 | # fatal error. | ||
187 | # | ||
188 | # CONFIGURATION PARAMETERS | ||
189 | # The following main.cf parameters are especially relevant. | ||
190 | # The text below provides only a parameter summary. See | ||
191 | # postconf(5) for more details including examples. | ||
192 | # | ||
193 | # alias_database (see 'postconf -d' output) | ||
194 | # The alias databases for local(8) delivery that are | ||
195 | # updated with "newaliases" or with "sendmail -bi". | ||
196 | # | ||
197 | # alias_maps (see 'postconf -d' output) | ||
198 | # The alias databases that are used for local(8) | ||
199 | # delivery. | ||
200 | # | ||
201 | # allow_mail_to_commands (alias, forward) | ||
202 | # Restrict local(8) mail delivery to external com- | ||
203 | # mands. | ||
204 | # | ||
205 | # allow_mail_to_files (alias, forward) | ||
206 | # Restrict local(8) mail delivery to external files. | ||
207 | # | ||
208 | # expand_owner_alias (no) | ||
209 | # When delivering to an alias "aliasname" that has an | ||
210 | # "owner-aliasname" companion alias, set the envelope | ||
211 | # sender address to the expansion of the | ||
212 | # "owner-aliasname" alias. | ||
213 | # | ||
214 | # propagate_unmatched_extensions (canonical, virtual) | ||
215 | # What address lookup tables copy an address exten- | ||
216 | # sion from the lookup key to the lookup result. | ||
217 | # | ||
218 | # owner_request_special (yes) | ||
219 | # Enable special treatment for owner-listname entries | ||
220 | # in the aliases(5) file, and don't split owner-list- | ||
221 | # name and listname-request address localparts when | ||
222 | # the recipient_delimiter is set to "-". | ||
223 | # | ||
224 | # recipient_delimiter (empty) | ||
225 | # The set of characters that can separate a user name | ||
226 | # from its extension (example: user+foo), or a .for- | ||
227 | # ward file name from its extension (example: .for- | ||
228 | # ward+foo). | ||
229 | # | ||
230 | # Available in Postfix version 2.3 and later: | ||
231 | # | ||
232 | # frozen_delivered_to (yes) | ||
233 | # Update the local(8) delivery agent's idea of the | ||
234 | # Delivered-To: address (see prepend_deliv- | ||
235 | # ered_header) only once, at the start of a delivery | ||
236 | # attempt; do not update the Delivered-To: address | ||
237 | # while expanding aliases or .forward files. | ||
238 | # | ||
239 | # STANDARDS | ||
240 | # RFC 822 (ARPA Internet Text Messages) | ||
241 | # | ||
242 | # SEE ALSO | ||
243 | # local(8), local delivery agent | ||
244 | # newaliases(1), create/update alias database | ||
245 | # postalias(1), create/update alias database | ||
246 | # postconf(5), configuration parameters | ||
247 | # | ||
248 | # README FILES | ||
249 | # Use "postconf readme_directory" or "postconf html_direc- | ||
250 | # tory" to locate this information. | ||
251 | # DATABASE_README, Postfix lookup table overview | ||
252 | # | ||
253 | # LICENSE | ||
254 | # The Secure Mailer license must be distributed with this | ||
255 | # software. | ||
256 | # | ||
257 | # AUTHOR(S) | ||
258 | # Wietse Venema | ||
259 | # IBM T.J. Watson Research | ||
260 | # P.O. Box 704 | ||
261 | # Yorktown Heights, NY 10598, USA | ||
262 | # | ||
263 | # Wietse Venema | ||
264 | # Google, Inc. | ||
265 | # 111 8th Avenue | ||
266 | # New York, NY 10011, USA | ||
267 | # | ||
268 | # ALIASES(5) | ||
diff --git a/postfix/main.cf b/postfix/main.cf new file mode 100644 index 0000000..5ef0f1d --- /dev/null +++ b/postfix/main.cf | |||
@@ -0,0 +1,701 @@ | |||
1 | # Global Postfix configuration file. This file lists only a subset | ||
2 | # of all parameters. For the syntax, and for a complete parameter | ||
3 | # list, see the postconf(5) manual page (command: "man 5 postconf"). | ||
4 | # | ||
5 | # For common configuration examples, see BASIC_CONFIGURATION_README | ||
6 | # and STANDARD_CONFIGURATION_README. To find these documents, use | ||
7 | # the command "postconf html_directory readme_directory", or go to | ||
8 | # http://www.postfix.org/BASIC_CONFIGURATION_README.html etc. | ||
9 | # | ||
10 | # For best results, change no more than 2-3 parameters at a time, | ||
11 | # and test if Postfix still works after every change. | ||
12 | |||
13 | # COMPATIBILITY | ||
14 | # | ||
15 | # The compatibility_level determines what default settings Postfix | ||
16 | # will use for main.cf and master.cf settings. These defaults will | ||
17 | # change over time. | ||
18 | # | ||
19 | # To avoid breaking things, Postfix will use backwards-compatible | ||
20 | # default settings and log where it uses those old backwards-compatible | ||
21 | # default settings, until the system administrator has determined | ||
22 | # if any backwards-compatible default settings need to be made | ||
23 | # permanent in main.cf or master.cf. | ||
24 | # | ||
25 | # When this review is complete, update the compatibility_level setting | ||
26 | # below as recommended in the RELEASE_NOTES file. | ||
27 | # | ||
28 | # The level below is what should be used with new (not upgrade) installs. | ||
29 | # | ||
30 | compatibility_level = 2 | ||
31 | |||
32 | # SOFT BOUNCE | ||
33 | # | ||
34 | # The soft_bounce parameter provides a limited safety net for | ||
35 | # testing. When soft_bounce is enabled, mail will remain queued that | ||
36 | # would otherwise bounce. This parameter disables locally-generated | ||
37 | # bounces, and prevents the SMTP server from rejecting mail permanently | ||
38 | # (by changing 5xx replies into 4xx replies). However, soft_bounce | ||
39 | # is no cure for address rewriting mistakes or mail routing mistakes. | ||
40 | # | ||
41 | soft_bounce = yes | ||
42 | |||
43 | # LOCAL PATHNAME INFORMATION | ||
44 | # | ||
45 | # The queue_directory specifies the location of the Postfix queue. | ||
46 | # This is also the root directory of Postfix daemons that run chrooted. | ||
47 | # See the files in examples/chroot-setup for setting up Postfix chroot | ||
48 | # environments on different UNIX systems. | ||
49 | # | ||
50 | queue_directory = /var/spool/postfix | ||
51 | |||
52 | # The command_directory parameter specifies the location of all | ||
53 | # postXXX commands. | ||
54 | # | ||
55 | command_directory = /usr/bin | ||
56 | |||
57 | # The daemon_directory parameter specifies the location of all Postfix | ||
58 | # daemon programs (i.e. programs listed in the master.cf file). This | ||
59 | # directory must be owned by root. | ||
60 | # | ||
61 | daemon_directory = /usr/lib/postfix/bin | ||
62 | |||
63 | # The data_directory parameter specifies the location of Postfix-writable | ||
64 | # data files (caches, random numbers). This directory must be owned | ||
65 | # by the mail_owner account (see below). | ||
66 | # | ||
67 | data_directory = /var/lib/postfix | ||
68 | |||
69 | # QUEUE AND PROCESS OWNERSHIP | ||
70 | # | ||
71 | # The mail_owner parameter specifies the owner of the Postfix queue | ||
72 | # and of most Postfix daemon processes. Specify the name of a user | ||
73 | # account THAT DOES NOT SHARE ITS USER OR GROUP ID WITH OTHER ACCOUNTS | ||
74 | # AND THAT OWNS NO OTHER FILES OR PROCESSES ON THE SYSTEM. In | ||
75 | # particular, don't specify nobody or daemon. PLEASE USE A DEDICATED | ||
76 | # USER. | ||
77 | # | ||
78 | mail_owner = postfix | ||
79 | |||
80 | # The default_privs parameter specifies the default rights used by | ||
81 | # the local delivery agent for delivery to external file or command. | ||
82 | # These rights are used in the absence of a recipient user context. | ||
83 | # DO NOT SPECIFY A PRIVILEGED USER OR THE POSTFIX OWNER. | ||
84 | # | ||
85 | #default_privs = nobody | ||
86 | |||
87 | # INTERNET HOST AND DOMAIN NAMES | ||
88 | # | ||
89 | # The myhostname parameter specifies the internet hostname of this | ||
90 | # mail system. The default is to use the fully-qualified domain name | ||
91 | # from gethostname(). $myhostname is used as a default value for many | ||
92 | # other configuration parameters. | ||
93 | # | ||
94 | myhostname = topo.tw | ||
95 | #myhostname = virtual.domain.tld | ||
96 | |||
97 | # The mydomain parameter specifies the local internet domain name. | ||
98 | # The default is to use $myhostname minus the first component. | ||
99 | # $mydomain is used as a default value for many other configuration | ||
100 | # parameters. | ||
101 | # | ||
102 | #mydomain = domain.tld | ||
103 | |||
104 | # SENDING MAIL | ||
105 | # | ||
106 | # The myorigin parameter specifies the domain that locally-posted | ||
107 | # mail appears to come from. The default is to append $myhostname, | ||
108 | # which is fine for small sites. If you run a domain with multiple | ||
109 | # machines, you should (1) change this to $mydomain and (2) set up | ||
110 | # a domain-wide alias database that aliases each user to | ||
111 | # user@that.users.mailhost. | ||
112 | # | ||
113 | # For the sake of consistency between sender and recipient addresses, | ||
114 | # myorigin also specifies the default domain name that is appended | ||
115 | # to recipient addresses that have no @domain part. | ||
116 | # | ||
117 | #myorigin = $myhostname | ||
118 | #myorigin = $mydomain | ||
119 | |||
120 | # RECEIVING MAIL | ||
121 | |||
122 | # The inet_interfaces parameter specifies the network interface | ||
123 | # addresses that this mail system receives mail on. By default, | ||
124 | # the software claims all active interfaces on the machine. The | ||
125 | # parameter also controls delivery of mail to user@[ip.address]. | ||
126 | # | ||
127 | # See also the proxy_interfaces parameter, for network addresses that | ||
128 | # are forwarded to us via a proxy or network address translator. | ||
129 | # | ||
130 | # Note: you need to stop/start Postfix when this parameter changes. | ||
131 | # | ||
132 | inet_interfaces = all | ||
133 | #inet_interfaces = $myhostname | ||
134 | #inet_interfaces = $myhostname, localhost | ||
135 | |||
136 | # The proxy_interfaces parameter specifies the network interface | ||
137 | # addresses that this mail system receives mail on by way of a | ||
138 | # proxy or network address translation unit. This setting extends | ||
139 | # the address list specified with the inet_interfaces parameter. | ||
140 | # | ||
141 | # You must specify your proxy/NAT addresses when your system is a | ||
142 | # backup MX host for other domains, otherwise mail delivery loops | ||
143 | # will happen when the primary MX host is down. | ||
144 | # | ||
145 | #proxy_interfaces = | ||
146 | #proxy_interfaces = 1.2.3.4 | ||
147 | |||
148 | # The mydestination parameter specifies the list of domains that this | ||
149 | # machine considers itself the final destination for. | ||
150 | # | ||
151 | # These domains are routed to the delivery agent specified with the | ||
152 | # local_transport parameter setting. By default, that is the UNIX | ||
153 | # compatible delivery agent that lookups all recipients in /etc/passwd | ||
154 | # and /etc/aliases or their equivalent. | ||
155 | # | ||
156 | # The default is $myhostname + localhost.$mydomain + localhost. On | ||
157 | # a mail domain gateway, you should also include $mydomain. | ||
158 | # | ||
159 | # Do not specify the names of virtual domains - those domains are | ||
160 | # specified elsewhere (see VIRTUAL_README). | ||
161 | # | ||
162 | # Do not specify the names of domains that this machine is backup MX | ||
163 | # host for. Specify those names via the relay_domains settings for | ||
164 | # the SMTP server, or use permit_mx_backup if you are lazy (see | ||
165 | # STANDARD_CONFIGURATION_README). | ||
166 | # | ||
167 | # The local machine is always the final destination for mail addressed | ||
168 | # to user@[the.net.work.address] of an interface that the mail system | ||
169 | # receives mail on (see the inet_interfaces parameter). | ||
170 | # | ||
171 | # Specify a list of host or domain names, /file/name or type:table | ||
172 | # patterns, separated by commas and/or whitespace. A /file/name | ||
173 | # pattern is replaced by its contents; a type:table is matched when | ||
174 | # a name matches a lookup key (the right-hand side is ignored). | ||
175 | # Continue long lines by starting the next line with whitespace. | ||
176 | # | ||
177 | # See also below, section "REJECTING MAIL FOR UNKNOWN LOCAL USERS". | ||
178 | # | ||
179 | mydestination = $myhostname, localhost.$mydomain, localhost | ||
180 | #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain | ||
181 | #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain, | ||
182 | # mail.$mydomain, www.$mydomain, ftp.$mydomain | ||
183 | |||
184 | # REJECTING MAIL FOR UNKNOWN LOCAL USERS | ||
185 | # | ||
186 | # The local_recipient_maps parameter specifies optional lookup tables | ||
187 | # with all names or addresses of users that are local with respect | ||
188 | # to $mydestination, $inet_interfaces or $proxy_interfaces. | ||
189 | # | ||
190 | # If this parameter is defined, then the SMTP server will reject | ||
191 | # mail for unknown local users. This parameter is defined by default. | ||
192 | # | ||
193 | # To turn off local recipient checking in the SMTP server, specify | ||
194 | # local_recipient_maps = (i.e. empty). | ||
195 | # | ||
196 | # The default setting assumes that you use the default Postfix local | ||
197 | # delivery agent for local delivery. You need to update the | ||
198 | # local_recipient_maps setting if: | ||
199 | # | ||
200 | # - You define $mydestination domain recipients in files other than | ||
201 | # /etc/passwd, /etc/aliases, or the $virtual_alias_maps files. | ||
202 | # For example, you define $mydestination domain recipients in | ||
203 | # the $virtual_mailbox_maps files. | ||
204 | # | ||
205 | # - You redefine the local delivery agent in master.cf. | ||
206 | # | ||
207 | # - You redefine the "local_transport" setting in main.cf. | ||
208 | # | ||
209 | # - You use the "luser_relay", "mailbox_transport", or "fallback_transport" | ||
210 | # feature of the Postfix local delivery agent (see local(8)). | ||
211 | # | ||
212 | # Details are described in the LOCAL_RECIPIENT_README file. | ||
213 | # | ||
214 | # Beware: if the Postfix SMTP server runs chrooted, you probably have | ||
215 | # to access the passwd file via the proxymap service, in order to | ||
216 | # overcome chroot restrictions. The alternative, having a copy of | ||
217 | # the system passwd file in the chroot jail is just not practical. | ||
218 | # | ||
219 | # The right-hand side of the lookup tables is conveniently ignored. | ||
220 | # In the left-hand side, specify a bare username, an @domain.tld | ||
221 | # wild-card, or specify a user@domain.tld address. | ||
222 | # | ||
223 | #local_recipient_maps = unix:passwd.byname $alias_maps | ||
224 | #local_recipient_maps = proxy:unix:passwd.byname $alias_maps | ||
225 | #local_recipient_maps = | ||
226 | virtual_alias_maps = hash:/etc/postfix/virtual | ||
227 | |||
228 | # The unknown_local_recipient_reject_code specifies the SMTP server | ||
229 | # response code when a recipient domain matches $mydestination or | ||
230 | # ${proxy,inet}_interfaces, while $local_recipient_maps is non-empty | ||
231 | # and the recipient address or address local-part is not found. | ||
232 | # | ||
233 | # The default setting is 550 (reject mail) but it is safer to start | ||
234 | # with 450 (try again later) until you are certain that your | ||
235 | # local_recipient_maps settings are OK. | ||
236 | # | ||
237 | unknown_local_recipient_reject_code = 550 | ||
238 | |||
239 | # TRUST AND RELAY CONTROL | ||
240 | |||
241 | # The mynetworks parameter specifies the list of "trusted" SMTP | ||
242 | # clients that have more privileges than "strangers". | ||
243 | # | ||
244 | # In particular, "trusted" SMTP clients are allowed to relay mail | ||
245 | # through Postfix. See the smtpd_recipient_restrictions parameter | ||
246 | # in postconf(5). | ||
247 | # | ||
248 | # You can specify the list of "trusted" network addresses by hand | ||
249 | # or you can let Postfix do it for you (which is the default). | ||
250 | # | ||
251 | # By default (mynetworks_style = subnet), Postfix "trusts" SMTP | ||
252 | # clients in the same IP subnetworks as the local machine. | ||
253 | # On Linux, this works correctly only with interfaces specified | ||
254 | # with the "ifconfig" command. | ||
255 | # | ||
256 | # Specify "mynetworks_style = class" when Postfix should "trust" SMTP | ||
257 | # clients in the same IP class A/B/C networks as the local machine. | ||
258 | # Don't do this with a dialup site - it would cause Postfix to "trust" | ||
259 | # your entire provider's network. Instead, specify an explicit | ||
260 | # mynetworks list by hand, as described below. | ||
261 | # | ||
262 | # Specify "mynetworks_style = host" when Postfix should "trust" | ||
263 | # only the local machine. | ||
264 | # | ||
265 | #mynetworks_style = class | ||
266 | #mynetworks_style = subnet | ||
267 | mynetworks_style = host | ||
268 | |||
269 | # Alternatively, you can specify the mynetworks list by hand, in | ||
270 | # which case Postfix ignores the mynetworks_style setting. | ||
271 | # | ||
272 | # Specify an explicit list of network/netmask patterns, where the | ||
273 | # mask specifies the number of bits in the network part of a host | ||
274 | # address. | ||
275 | # | ||
276 | # You can also specify the absolute pathname of a pattern file instead | ||
277 | # of listing the patterns here. Specify type:table for table-based lookups | ||
278 | # (the value on the table right-hand side is not used). | ||
279 | # | ||
280 | #mynetworks = 168.100.189.0/28, 127.0.0.0/8 | ||
281 | #mynetworks = $config_directory/mynetworks | ||
282 | #mynetworks = hash:/etc/postfix/network_table | ||
283 | |||
284 | # The relay_domains parameter restricts what destinations this system will | ||
285 | # relay mail to. See the smtpd_recipient_restrictions description in | ||
286 | # postconf(5) for detailed information. | ||
287 | # | ||
288 | # By default, Postfix relays mail | ||
289 | # - from "trusted" clients (IP address matches $mynetworks) to any destination, | ||
290 | # - from "untrusted" clients to destinations that match $relay_domains or | ||
291 | # subdomains thereof, except addresses with sender-specified routing. | ||
292 | # The default relay_domains value is $mydestination. | ||
293 | # | ||
294 | # In addition to the above, the Postfix SMTP server by default accepts mail | ||
295 | # that Postfix is final destination for: | ||
296 | # - destinations that match $inet_interfaces or $proxy_interfaces, | ||
297 | # - destinations that match $mydestination | ||
298 | # - destinations that match $virtual_alias_domains, | ||
299 | # - destinations that match $virtual_mailbox_domains. | ||
300 | # These destinations do not need to be listed in $relay_domains. | ||
301 | # | ||
302 | # Specify a list of hosts or domains, /file/name patterns or type:name | ||
303 | # lookup tables, separated by commas and/or whitespace. Continue | ||
304 | # long lines by starting the next line with whitespace. A file name | ||
305 | # is replaced by its contents; a type:name table is matched when a | ||
306 | # (parent) domain appears as lookup key. | ||
307 | # | ||
308 | # NOTE: Postfix will not automatically forward mail for domains that | ||
309 | # list this system as their primary or backup MX host. See the | ||
310 | # permit_mx_backup restriction description in postconf(5). | ||
311 | # | ||
312 | #relay_domains = $mydestination | ||
313 | |||
314 | # INTERNET OR INTRANET | ||
315 | |||
316 | # The relayhost parameter specifies the default host to send mail to | ||
317 | # when no entry is matched in the optional transport(5) table. When | ||
318 | # no relayhost is given, mail is routed directly to the destination. | ||
319 | # | ||
320 | # On an intranet, specify the organizational domain name. If your | ||
321 | # internal DNS uses no MX records, specify the name of the intranet | ||
322 | # gateway host instead. | ||
323 | # | ||
324 | # In the case of SMTP, specify a domain, host, host:port, [host]:port, | ||
325 | # [address] or [address]:port; the form [host] turns off MX lookups. | ||
326 | # | ||
327 | # If you're connected via UUCP, see also the default_transport parameter. | ||
328 | # | ||
329 | #relayhost = $mydomain | ||
330 | #relayhost = [gateway.my.domain] | ||
331 | #relayhost = [mailserver.isp.tld] | ||
332 | #relayhost = uucphost | ||
333 | #relayhost = [an.ip.add.ress] | ||
334 | |||
335 | # REJECTING UNKNOWN RELAY USERS | ||
336 | # | ||
337 | # The relay_recipient_maps parameter specifies optional lookup tables | ||
338 | # with all addresses in the domains that match $relay_domains. | ||
339 | # | ||
340 | # If this parameter is defined, then the SMTP server will reject | ||
341 | # mail for unknown relay users. This feature is off by default. | ||
342 | # | ||
343 | # The right-hand side of the lookup tables is conveniently ignored. | ||
344 | # In the left-hand side, specify an @domain.tld wild-card, or specify | ||
345 | # a user@domain.tld address. | ||
346 | # | ||
347 | #relay_recipient_maps = hash:/etc/postfix/relay_recipients | ||
348 | |||
349 | # INPUT RATE CONTROL | ||
350 | # | ||
351 | # The in_flow_delay configuration parameter implements mail input | ||
352 | # flow control. This feature is turned on by default, although it | ||
353 | # still needs further development (it's disabled on SCO UNIX due | ||
354 | # to an SCO bug). | ||
355 | # | ||
356 | # A Postfix process will pause for $in_flow_delay seconds before | ||
357 | # accepting a new message, when the message arrival rate exceeds the | ||
358 | # message delivery rate. With the default 100 SMTP server process | ||
359 | # limit, this limits the mail inflow to 100 messages a second more | ||
360 | # than the number of messages delivered per second. | ||
361 | # | ||
362 | # Specify 0 to disable the feature. Valid delays are 0..10. | ||
363 | # | ||
364 | #in_flow_delay = 1s | ||
365 | |||
366 | # ADDRESS REWRITING | ||
367 | # | ||
368 | # The ADDRESS_REWRITING_README document gives information about | ||
369 | # address masquerading or other forms of address rewriting including | ||
370 | # username->Firstname.Lastname mapping. | ||
371 | |||
372 | # ADDRESS REDIRECTION (VIRTUAL DOMAIN) | ||
373 | # | ||
374 | # The VIRTUAL_README document gives information about the many forms | ||
375 | # of domain hosting that Postfix supports. | ||
376 | |||
377 | # "USER HAS MOVED" BOUNCE MESSAGES | ||
378 | # | ||
379 | # See the discussion in the ADDRESS_REWRITING_README document. | ||
380 | |||
381 | # TRANSPORT MAP | ||
382 | # | ||
383 | # See the discussion in the ADDRESS_REWRITING_README document. | ||
384 | |||
385 | # ALIAS DATABASE | ||
386 | # | ||
387 | # The alias_maps parameter specifies the list of alias databases used | ||
388 | # by the local delivery agent. The default list is system dependent. | ||
389 | # | ||
390 | # On systems with NIS, the default is to search the local alias | ||
391 | # database, then the NIS alias database. See aliases(5) for syntax | ||
392 | # details. | ||
393 | # | ||
394 | # If you change the alias database, run "postalias /etc/aliases" (or | ||
395 | # wherever your system stores the mail alias file), or simply run | ||
396 | # "newaliases" to build the necessary DBM or DB file. | ||
397 | # | ||
398 | # It will take a minute or so before changes become visible. Use | ||
399 | # "postfix reload" to eliminate the delay. | ||
400 | # | ||
401 | #alias_maps = dbm:/etc/aliases | ||
402 | #alias_maps = hash:/etc/aliases | ||
403 | #alias_maps = hash:/etc/aliases, nis:mail.aliases | ||
404 | #alias_maps = netinfo:/aliases | ||
405 | alias_maps = hash:/etc/postfix/aliases | ||
406 | |||
407 | # The alias_database parameter specifies the alias database(s) that | ||
408 | # are built with "newaliases" or "sendmail -bi". This is a separate | ||
409 | # configuration parameter, because alias_maps (see above) may specify | ||
410 | # tables that are not necessarily all under control by Postfix. | ||
411 | # | ||
412 | #alias_database = dbm:/etc/aliases | ||
413 | #alias_database = dbm:/etc/mail/aliases | ||
414 | #alias_database = hash:/etc/aliases | ||
415 | #alias_database = hash:/etc/aliases, hash:/opt/majordomo/aliases | ||
416 | alias_database = $alias_maps | ||
417 | |||
418 | # ADDRESS EXTENSIONS (e.g., user+foo) | ||
419 | # | ||
420 | # The recipient_delimiter parameter specifies the separator between | ||
421 | # user names and address extensions (user+foo). See canonical(5), | ||
422 | # local(8), relocated(5) and virtual(5) for the effects this has on | ||
423 | # aliases, canonical, virtual, relocated and .forward file lookups. | ||
424 | # Basically, the software tries user+foo and .forward+foo before | ||
425 | # trying user and .forward. | ||
426 | # | ||
427 | #recipient_delimiter = + | ||
428 | |||
429 | # DELIVERY TO MAILBOX | ||
430 | # | ||
431 | # The home_mailbox parameter specifies the optional pathname of a | ||
432 | # mailbox file relative to a user's home directory. The default | ||
433 | # mailbox file is /var/spool/mail/user or /var/mail/user. Specify | ||
434 | # "Maildir/" for qmail-style delivery (the / is required). | ||
435 | # | ||
436 | #home_mailbox = Mailbox | ||
437 | home_mailbox = Maildir/ | ||
438 | |||
439 | # The mail_spool_directory parameter specifies the directory where | ||
440 | # UNIX-style mailboxes are kept. The default setting depends on the | ||
441 | # system type. | ||
442 | # | ||
443 | #mail_spool_directory = /var/mail | ||
444 | #mail_spool_directory = /var/spool/mail | ||
445 | |||
446 | # The mailbox_command parameter specifies the optional external | ||
447 | # command to use instead of mailbox delivery. The command is run as | ||
448 | # the recipient with proper HOME, SHELL and LOGNAME environment settings. | ||
449 | # Exception: delivery for root is done as $default_user. | ||
450 | # | ||
451 | # Other environment variables of interest: USER (recipient username), | ||
452 | # EXTENSION (address extension), DOMAIN (domain part of address), | ||
453 | # and LOCAL (the address localpart). | ||
454 | # | ||
455 | # Unlike other Postfix configuration parameters, the mailbox_command | ||
456 | # parameter is not subjected to $parameter substitutions. This is to | ||
457 | # make it easier to specify shell syntax (see example below). | ||
458 | # | ||
459 | # Avoid shell meta characters because they will force Postfix to run | ||
460 | # an expensive shell process. Procmail alone is expensive enough. | ||
461 | # | ||
462 | # IF YOU USE THIS TO DELIVER MAIL SYSTEM-WIDE, YOU MUST SET UP AN | ||
463 | # ALIAS THAT FORWARDS MAIL FOR ROOT TO A REAL USER. | ||
464 | # | ||
465 | mailbox_command = /usr/lib/dovecot/dovecot-lda | ||
466 | #mailbox_command = /some/where/procmail -a "$EXTENSION" | ||
467 | |||
468 | # The mailbox_transport specifies the optional transport in master.cf | ||
469 | # to use after processing aliases and .forward files. This parameter | ||
470 | # has precedence over the mailbox_command, fallback_transport and | ||
471 | # luser_relay parameters. | ||
472 | # | ||
473 | # Specify a string of the form transport:nexthop, where transport is | ||
474 | # the name of a mail delivery transport defined in master.cf. The | ||
475 | # :nexthop part is optional. For more details see the sample transport | ||
476 | # configuration file. | ||
477 | # | ||
478 | # NOTE: if you use this feature for accounts not in the UNIX password | ||
479 | # file, then you must update the "local_recipient_maps" setting in | ||
480 | # the main.cf file, otherwise the SMTP server will reject mail for | ||
481 | # non-UNIX accounts with "User unknown in local recipient table". | ||
482 | # | ||
483 | # Cyrus IMAP over LMTP. Specify ``lmtpunix cmd="lmtpd" | ||
484 | # listen="/var/imap/socket/lmtp" prefork=0'' in cyrus.conf. | ||
485 | #mailbox_transport = lmtp:unix:/var/imap/socket/lmtp | ||
486 | # | ||
487 | # Cyrus IMAP via command line. Uncomment the "cyrus...pipe" and | ||
488 | # subsequent line in master.cf. | ||
489 | #mailbox_transport = cyrus | ||
490 | |||
491 | # The fallback_transport specifies the optional transport in master.cf | ||
492 | # to use for recipients that are not found in the UNIX passwd database. | ||
493 | # This parameter has precedence over the luser_relay parameter. | ||
494 | # | ||
495 | # Specify a string of the form transport:nexthop, where transport is | ||
496 | # the name of a mail delivery transport defined in master.cf. The | ||
497 | # :nexthop part is optional. For more details see the sample transport | ||
498 | # configuration file. | ||
499 | # | ||
500 | # NOTE: if you use this feature for accounts not in the UNIX password | ||
501 | # file, then you must update the "local_recipient_maps" setting in | ||
502 | # the main.cf file, otherwise the SMTP server will reject mail for | ||
503 | # non-UNIX accounts with "User unknown in local recipient table". | ||
504 | # | ||
505 | #fallback_transport = lmtp:unix:/file/name | ||
506 | #fallback_transport = cyrus | ||
507 | #fallback_transport = | ||
508 | |||
509 | # The luser_relay parameter specifies an optional destination address | ||
510 | # for unknown recipients. By default, mail for unknown@$mydestination, | ||
511 | # unknown@[$inet_interfaces] or unknown@[$proxy_interfaces] is returned | ||
512 | # as undeliverable. | ||
513 | # | ||
514 | # The following expansions are done on luser_relay: $user (recipient | ||
515 | # username), $shell (recipient shell), $home (recipient home directory), | ||
516 | # $recipient (full recipient address), $extension (recipient address | ||
517 | # extension), $domain (recipient domain), $local (entire recipient | ||
518 | # localpart), $recipient_delimiter. Specify ${name?value} or | ||
519 | # ${name:value} to expand value only when $name does (does not) exist. | ||
520 | # | ||
521 | # luser_relay works only for the default Postfix local delivery agent. | ||
522 | # | ||
523 | # NOTE: if you use this feature for accounts not in the UNIX password | ||
524 | # file, then you must specify "local_recipient_maps =" (i.e. empty) in | ||
525 | # the main.cf file, otherwise the SMTP server will reject mail for | ||
526 | # non-UNIX accounts with "User unknown in local recipient table". | ||
527 | # | ||
528 | #luser_relay = $user@other.host | ||
529 | #luser_relay = $local@other.host | ||
530 | #luser_relay = admin+$local | ||
531 | |||
532 | # JUNK MAIL CONTROLS | ||
533 | # | ||
534 | # The controls listed here are only a very small subset. The file | ||
535 | # SMTPD_ACCESS_README provides an overview. | ||
536 | |||
537 | # The header_checks parameter specifies an optional table with patterns | ||
538 | # that each logical message header is matched against, including | ||
539 | # headers that span multiple physical lines. | ||
540 | # | ||
541 | # By default, these patterns also apply to MIME headers and to the | ||
542 | # headers of attached messages. With older Postfix versions, MIME and | ||
543 | # attached message headers were treated as body text. | ||
544 | # | ||
545 | # For details, see "man header_checks". | ||
546 | # | ||
547 | #header_checks = regexp:/etc/postfix/header_checks | ||
548 | |||
549 | # FAST ETRN SERVICE | ||
550 | # | ||
551 | # Postfix maintains per-destination logfiles with information about | ||
552 | # deferred mail, so that mail can be flushed quickly with the SMTP | ||
553 | # "ETRN domain.tld" command, or by executing "sendmail -qRdomain.tld". | ||
554 | # See the ETRN_README document for a detailed description. | ||
555 | # | ||
556 | # The fast_flush_domains parameter controls what destinations are | ||
557 | # eligible for this service. By default, they are all domains that | ||
558 | # this server is willing to relay mail to. | ||
559 | # | ||
560 | #fast_flush_domains = $relay_domains | ||
561 | |||
562 | # SHOW SOFTWARE VERSION OR NOT | ||
563 | # | ||
564 | # The smtpd_banner parameter specifies the text that follows the 220 | ||
565 | # code in the SMTP server's greeting banner. Some people like to see | ||
566 | # the mail version advertised. By default, Postfix shows no version. | ||
567 | # | ||
568 | # You MUST specify $myhostname at the start of the text. That is an | ||
569 | # RFC requirement. Postfix itself does not care. | ||
570 | # | ||
571 | #smtpd_banner = $myhostname ESMTP $mail_name | ||
572 | smtpd_banner = $myhostname ESMTP $mail_name ($mail_version) | ||
573 | |||
574 | # PARALLEL DELIVERY TO THE SAME DESTINATION | ||
575 | # | ||
576 | # How many parallel deliveries to the same user or domain? With local | ||
577 | # delivery, it does not make sense to do massively parallel delivery | ||
578 | # to the same user, because mailbox updates must happen sequentially, | ||
579 | # and expensive pipelines in .forward files can cause disasters when | ||
580 | # too many are run at the same time. With SMTP deliveries, 10 | ||
581 | # simultaneous connections to the same domain could be sufficient to | ||
582 | # raise eyebrows. | ||
583 | # | ||
584 | # Each message delivery transport has its XXX_destination_concurrency_limit | ||
585 | # parameter. The default is $default_destination_concurrency_limit for | ||
586 | # most delivery transports. For the local delivery agent the default is 2. | ||
587 | |||
588 | #local_destination_concurrency_limit = 2 | ||
589 | #default_destination_concurrency_limit = 20 | ||
590 | |||
591 | # DEBUGGING CONTROL | ||
592 | # | ||
593 | # The debug_peer_level parameter specifies the increment in verbose | ||
594 | # logging level when an SMTP client or server host name or address | ||
595 | # matches a pattern in the debug_peer_list parameter. | ||
596 | # | ||
597 | debug_peer_level = 2 | ||
598 | |||
599 | # The debug_peer_list parameter specifies an optional list of domain | ||
600 | # or network patterns, /file/name patterns or type:name tables. When | ||
601 | # an SMTP client or server host name or address matches a pattern, | ||
602 | # increase the verbose logging level by the amount specified in the | ||
603 | # debug_peer_level parameter. | ||
604 | # | ||
605 | #debug_peer_list = 127.0.0.1 | ||
606 | #debug_peer_list = some.domain | ||
607 | |||
608 | # The debugger_command specifies the external command that is executed | ||
609 | # when a Postfix daemon program is run with the -D option. | ||
610 | # | ||
611 | # Use "command .. & sleep 5" so that the debugger can attach before | ||
612 | # the process marches on. If you use an X-based debugger, be sure to | ||
613 | # set up your XAUTHORITY environment variable before starting Postfix. | ||
614 | # | ||
615 | debugger_command = | ||
616 | PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin | ||
617 | ddd $daemon_directory/$process_name $process_id & sleep 5 | ||
618 | |||
619 | # If you can't use X, use this to capture the call stack when a | ||
620 | # daemon crashes. The result is in a file in the configuration | ||
621 | # directory, and is named after the process name and the process ID. | ||
622 | # | ||
623 | # debugger_command = | ||
624 | # PATH=/bin:/usr/bin:/usr/local/bin; export PATH; (echo cont; | ||
625 | # echo where) | gdb $daemon_directory/$process_name $process_id 2>&1 | ||
626 | # >$config_directory/$process_name.$process_id.log & sleep 5 | ||
627 | # | ||
628 | # Another possibility is to run gdb under a detached screen session. | ||
629 | # To attach to the screen session, su root and run "screen -r | ||
630 | # <id_string>" where <id_string> uniquely matches one of the detached | ||
631 | # sessions (from "screen -list"). | ||
632 | # | ||
633 | # debugger_command = | ||
634 | # PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH; screen | ||
635 | # -dmS $process_name gdb $daemon_directory/$process_name | ||
636 | # $process_id & sleep 1 | ||
637 | |||
638 | # INSTALL-TIME CONFIGURATION INFORMATION | ||
639 | # | ||
640 | # The following parameters are used when installing a new Postfix version. | ||
641 | # | ||
642 | # sendmail_path: The full pathname of the Postfix sendmail command. | ||
643 | # This is the Sendmail-compatible mail posting interface. | ||
644 | # | ||
645 | sendmail_path = /usr/bin/sendmail | ||
646 | |||
647 | # newaliases_path: The full pathname of the Postfix newaliases command. | ||
648 | # This is the Sendmail-compatible command to build alias databases. | ||
649 | # | ||
650 | newaliases_path = /usr/bin/newaliases | ||
651 | |||
652 | # mailq_path: The full pathname of the Postfix mailq command. This | ||
653 | # is the Sendmail-compatible mail queue listing command. | ||
654 | # | ||
655 | mailq_path = /usr/bin/mailq | ||
656 | |||
657 | # setgid_group: The group for mail submission and queue management | ||
658 | # commands. This must be a group name with a numerical group ID that | ||
659 | # is not shared with other accounts, not even with the Postfix account. | ||
660 | # | ||
661 | setgid_group = postdrop | ||
662 | |||
663 | # html_directory: The location of the Postfix HTML documentation. | ||
664 | # | ||
665 | html_directory = no | ||
666 | |||
667 | # manpage_directory: The location of the Postfix on-line manual pages. | ||
668 | # | ||
669 | manpage_directory = /usr/share/man | ||
670 | |||
671 | # sample_directory: The location of the Postfix sample configuration files. | ||
672 | # This parameter is obsolete as of Postfix 2.1. | ||
673 | # | ||
674 | sample_directory = /etc/postfix | ||
675 | |||
676 | # readme_directory: The location of the Postfix README files. | ||
677 | # | ||
678 | readme_directory = /usr/share/doc/postfix | ||
679 | inet_protocols = ipv4 | ||
680 | meta_directory = /etc/postfix | ||
681 | shlib_directory = /usr/lib/postfix | ||
682 | |||
683 | smtpd_sasl_type = dovecot | ||
684 | smtpd_sasl_path = private/auth | ||
685 | smtpd_sasl_auth_enable = yes | ||
686 | smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination | ||
687 | |||
688 | smtp_tls_security_level = may | ||
689 | smtpd_tls_security_level = may | ||
690 | smtpd_use_tls = yes | ||
691 | smtpd_tls_auth_only = yes | ||
692 | smtpd_tls_cert_file = /etc/letsencrypt/live/mail.topo.tw/fullchain.pem | ||
693 | smtpd_tls_key_file = /etc/letsencrypt/live/mail.topo.tw/privkey.pem | ||
694 | smtpd_tls_loglevel = 1 | ||
695 | maillog_file=/var/log/postfix.log | ||
696 | message_size_limit = 40960000 | ||
697 | mailbox_size_limit = 10000000000 | ||
698 | |||
699 | smtpd_milters = inet:localhost:8891 | ||
700 | non_smtpd_milters = $smtpd_milters | ||
701 | milter_default_action = accept | ||
diff --git a/postfix/master.cf b/postfix/master.cf new file mode 100644 index 0000000..883a466 --- /dev/null +++ b/postfix/master.cf | |||
@@ -0,0 +1,141 @@ | |||
1 | # | ||
2 | # Postfix master process configuration file. For details on the format | ||
3 | # of the file, see the master(5) manual page (command: "man 5 master" or | ||
4 | # on-line: http://www.postfix.org/master.5.html). | ||
5 | # | ||
6 | # Do not forget to execute "postfix reload" after editing this file. | ||
7 | # | ||
8 | # ========================================================================== | ||
9 | # service type private unpriv chroot wakeup maxproc command + args | ||
10 | # (yes) (yes) (no) (never) (100) | ||
11 | # ========================================================================== | ||
12 | smtp inet n - n - - smtpd | ||
13 | #smtp inet n - n - - smtpd -o content_filter=myhook:dummy | ||
14 | #smtp inet n - n - 1 postscreen | ||
15 | #smtpd pass - - n - - smtpd | ||
16 | #dnsblog unix - - n - 0 dnsblog | ||
17 | #tlsproxy unix - - n - 0 tlsproxy | ||
18 | # Choose one: enable submission for loopback clients only, or for any client. | ||
19 | #127.0.0.1:submission inet n - n - - smtpd | ||
20 | submission inet n - n - - smtpd | ||
21 | -o syslog_name=postfix/submission | ||
22 | -o smtpd_tls_security_level=encrypt | ||
23 | -o smtpd_sasl_auth_enable=yes | ||
24 | # -o smtpd_tls_auth_only=yes | ||
25 | # -o smtpd_reject_unlisted_recipient=no | ||
26 | # -o smtpd_client_restrictions=$mua_client_restrictions | ||
27 | # -o smtpd_helo_restrictions=$mua_helo_restrictions | ||
28 | # -o smtpd_sender_restrictions=$mua_sender_restrictions | ||
29 | # -o smtpd_recipient_restrictions= | ||
30 | # -o smtpd_relay_restrictions=permit_sasl_authenticated,reject | ||
31 | # -o milter_macro_daemon_name=ORIGINATING | ||
32 | # Choose one: enable smtps for loopback clients only, or for any client. | ||
33 | #127.0.0.1:smtps inet n - n - - smtpd | ||
34 | #smtps inet n - n - - smtpd | ||
35 | # -o syslog_name=postfix/smtps | ||
36 | # -o smtpd_tls_wrappermode=yes | ||
37 | # -o smtpd_sasl_auth_enable=yes | ||
38 | # -o smtpd_reject_unlisted_recipient=no | ||
39 | # -o smtpd_client_restrictions=$mua_client_restrictions | ||
40 | # -o smtpd_helo_restrictions=$mua_helo_restrictions | ||
41 | # -o smtpd_sender_restrictions=$mua_sender_restrictions | ||
42 | # -o smtpd_recipient_restrictions= | ||
43 | # -o smtpd_relay_restrictions=permit_sasl_authenticated,reject | ||
44 | # -o milter_macro_daemon_name=ORIGINATING | ||
45 | #628 inet n - n - - qmqpd | ||
46 | pickup unix n - n 60 1 pickup | ||
47 | cleanup unix n - n - 0 cleanup | ||
48 | qmgr unix n - n 300 1 qmgr | ||
49 | #qmgr unix n - n 300 1 oqmgr | ||
50 | tlsmgr unix - - n 1000? 1 tlsmgr | ||
51 | rewrite unix - - n - - trivial-rewrite | ||
52 | bounce unix - - n - 0 bounce | ||
53 | defer unix - - n - 0 bounce | ||
54 | trace unix - - n - 0 bounce | ||
55 | verify unix - - n - 1 verify | ||
56 | flush unix n - n 1000? 0 flush | ||
57 | proxymap unix - - n - - proxymap | ||
58 | proxywrite unix - - n - 1 proxymap | ||
59 | smtp unix - - n - - smtp | ||
60 | relay unix - - n - - smtp | ||
61 | -o syslog_name=postfix/$service_name | ||
62 | # -o smtp_helo_timeout=5 -o smtp_connect_timeout=5 | ||
63 | showq unix n - n - - showq | ||
64 | error unix - - n - - error | ||
65 | retry unix - - n - - error | ||
66 | discard unix - - n - - discard | ||
67 | local unix - n n - - local | ||
68 | virtual unix - n n - - virtual | ||
69 | lmtp unix - - n - - lmtp | ||
70 | anvil unix - - n - 1 anvil | ||
71 | scache unix - - n - 1 scache | ||
72 | postlog unix-dgram n - n - 1 postlogd | ||
73 | # | ||
74 | # ==================================================================== | ||
75 | # Interfaces to non-Postfix software. Be sure to examine the manual | ||
76 | # pages of the non-Postfix software to find out what options it wants. | ||
77 | # | ||
78 | # Many of the following services use the Postfix pipe(8) delivery | ||
79 | # agent. See the pipe(8) man page for information about ${recipient} | ||
80 | # and other message envelope options. | ||
81 | # ==================================================================== | ||
82 | # | ||
83 | # maildrop. See the Postfix MAILDROP_README file for details. | ||
84 | # Also specify in main.cf: maildrop_destination_recipient_limit=1 | ||
85 | # | ||
86 | #maildrop unix - n n - - pipe | ||
87 | # flags=DRXhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient} | ||
88 | # | ||
89 | # ==================================================================== | ||
90 | # | ||
91 | # Recent Cyrus versions can use the existing "lmtp" master.cf entry. | ||
92 | # | ||
93 | # Specify in cyrus.conf: | ||
94 | # lmtp cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4 | ||
95 | # | ||
96 | # Specify in main.cf one or more of the following: | ||
97 | # mailbox_transport = lmtp:inet:localhost | ||
98 | # virtual_transport = lmtp:inet:localhost | ||
99 | # | ||
100 | # ==================================================================== | ||
101 | # | ||
102 | # Cyrus 2.1.5 (Amos Gouaux) | ||
103 | # Also specify in main.cf: cyrus_destination_recipient_limit=1 | ||
104 | # | ||
105 | #cyrus unix - n n - - pipe | ||
106 | # flags=DRX user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user} | ||
107 | # | ||
108 | # ==================================================================== | ||
109 | # | ||
110 | # Old example of delivery via Cyrus. | ||
111 | # | ||
112 | #old-cyrus unix - n n - - pipe | ||
113 | # flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user} | ||
114 | # | ||
115 | # ==================================================================== | ||
116 | # | ||
117 | # See the Postfix UUCP_README file for configuration details. | ||
118 | # | ||
119 | #uucp unix - n n - - pipe | ||
120 | # flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient) | ||
121 | # | ||
122 | # ==================================================================== | ||
123 | # | ||
124 | # Other external delivery methods. | ||
125 | # | ||
126 | #ifmail unix - n n - - pipe | ||
127 | # flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient) | ||
128 | # | ||
129 | #bsmtp unix - n n - - pipe | ||
130 | # flags=Fq. user=bsmtp argv=/usr/local/sbin/bsmtp -f $sender $nexthop $recipient | ||
131 | # | ||
132 | #scalemail-backend unix - n n - 2 pipe | ||
133 | # flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store | ||
134 | # ${nexthop} ${user} ${extension} | ||
135 | # | ||
136 | #mailman unix - n n - - pipe | ||
137 | # flags=FRX user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py | ||
138 | # ${nexthop} ${user} | ||
139 | # | ||
140 | |||
141 | myhook unix - n n - - pipe flags=F user=pham argv=/home/pham/scripts/postfix-test ${sender} ${size} ${recipient} | ||
diff --git a/postfix/opendkim/opendkim.conf b/postfix/opendkim/opendkim.conf new file mode 100644 index 0000000..5c8c65e --- /dev/null +++ b/postfix/opendkim/opendkim.conf | |||
@@ -0,0 +1,6 @@ | |||
1 | Mode s | ||
2 | Domain topo.tw | ||
3 | KeyFile /etc/opendkim/dkim.key | ||
4 | Selector dkim | ||
5 | Socket inet:8891@localhost | ||
6 | UserID opendkim | ||
diff --git a/postfix/virtual b/postfix/virtual new file mode 100644 index 0000000..ca8fb33 --- /dev/null +++ b/postfix/virtual | |||
@@ -0,0 +1,328 @@ | |||
1 | @topo.tw pham | ||
2 | #no-reply@topo.tw devnull | ||
3 | #dmarc@topo.tw devnull | ||
4 | |||
5 | # VIRTUAL(5) VIRTUAL(5) | ||
6 | # | ||
7 | # NAME | ||
8 | # virtual - Postfix virtual alias table format | ||
9 | # | ||
10 | # SYNOPSIS | ||
11 | # postmap /etc/postfix/virtual | ||
12 | # | ||
13 | # postmap -q "string" /etc/postfix/virtual | ||
14 | # | ||
15 | # postmap -q - /etc/postfix/virtual <inputfile | ||
16 | # | ||
17 | # DESCRIPTION | ||
18 | # The optional virtual(5) alias table rewrites recipient | ||
19 | # addresses for all local, all virtual, and all remote mail | ||
20 | # destinations. This is unlike the aliases(5) table which | ||
21 | # is used only for local(8) delivery. Virtual aliasing is | ||
22 | # recursive, and is implemented by the Postfix cleanup(8) | ||
23 | # daemon before mail is queued. | ||
24 | # | ||
25 | # The main applications of virtual aliasing are: | ||
26 | # | ||
27 | # o To redirect mail for one address to one or more | ||
28 | # addresses. | ||
29 | # | ||
30 | # o To implement virtual alias domains where all | ||
31 | # addresses are aliased to addresses in other | ||
32 | # domains. | ||
33 | # | ||
34 | # Virtual alias domains are not to be confused with | ||
35 | # the virtual mailbox domains that are implemented | ||
36 | # with the Postfix virtual(8) mail delivery agent. | ||
37 | # With virtual mailbox domains, each recipient | ||
38 | # address can have its own mailbox. | ||
39 | # | ||
40 | # Virtual aliasing is applied only to recipient envelope | ||
41 | # addresses, and does not affect message headers. Use | ||
42 | # canonical(5) mapping to rewrite header and envelope | ||
43 | # addresses in general. | ||
44 | # | ||
45 | # Normally, the virtual(5) alias table is specified as a | ||
46 | # text file that serves as input to the postmap(1) command. | ||
47 | # The result, an indexed file in dbm or db format, is used | ||
48 | # for fast searching by the mail system. Execute the command | ||
49 | # "postmap /etc/postfix/virtual" to rebuild an indexed file | ||
50 | # after changing the corresponding text file. | ||
51 | # | ||
52 | # When the table is provided via other means such as NIS, | ||
53 | # LDAP or SQL, the same lookups are done as for ordinary | ||
54 | # indexed files. | ||
55 | # | ||
56 | # Alternatively, the table can be provided as a regu- | ||
57 | # lar-expression map where patterns are given as regular | ||
58 | # expressions, or lookups can be directed to TCP-based | ||
59 | # server. In those case, the lookups are done in a slightly | ||
60 | # different way as described below under "REGULAR EXPRESSION | ||
61 | # TABLES" or "TCP-BASED TABLES". | ||
62 | # | ||
63 | # CASE FOLDING | ||
64 | # The search string is folded to lowercase before database | ||
65 | # lookup. As of Postfix 2.3, the search string is not case | ||
66 | # folded with database types such as regexp: or pcre: whose | ||
67 | # lookup fields can match both upper and lower case. | ||
68 | # | ||
69 | # TABLE FORMAT | ||
70 | # The input format for the postmap(1) command is as follows: | ||
71 | # | ||
72 | # pattern address, address, ... | ||
73 | # When pattern matches a mail address, replace it by | ||
74 | # the corresponding address. | ||
75 | # | ||
76 | # blank lines and comments | ||
77 | # Empty lines and whitespace-only lines are ignored, | ||
78 | # as are lines whose first non-whitespace character | ||
79 | # is a `#'. | ||
80 | # | ||
81 | # multi-line text | ||
82 | # A logical line starts with non-whitespace text. A | ||
83 | # line that starts with whitespace continues a logi- | ||
84 | # cal line. | ||
85 | # | ||
86 | # TABLE SEARCH ORDER | ||
87 | # With lookups from indexed files such as DB or DBM, or from | ||
88 | # networked tables such as NIS, LDAP or SQL, each | ||
89 | # user@domain query produces a sequence of query patterns as | ||
90 | # described below. | ||
91 | # | ||
92 | # Each query pattern is sent to each specified lookup table | ||
93 | # before trying the next query pattern, until a match is | ||
94 | # found. | ||
95 | # | ||
96 | # user@domain address, address, ... | ||
97 | # Redirect mail for user@domain to address. This | ||
98 | # form has the highest precedence. | ||
99 | # | ||
100 | # user address, address, ... | ||
101 | # Redirect mail for user@site to address when site is | ||
102 | # equal to $myorigin, when site is listed in $mydes- | ||
103 | # tination, or when it is listed in $inet_interfaces | ||
104 | # or $proxy_interfaces. | ||
105 | # | ||
106 | # This functionality overlaps with functionality of | ||
107 | # the local aliases(5) database. The difference is | ||
108 | # that virtual(5) mapping can be applied to non-local | ||
109 | # addresses. | ||
110 | # | ||
111 | # @domain address, address, ... | ||
112 | # Redirect mail for other users in domain to address. | ||
113 | # This form has the lowest precedence. | ||
114 | # | ||
115 | # Note: @domain is a wild-card. With this form, the | ||
116 | # Postfix SMTP server accepts mail for any recipient | ||
117 | # in domain, regardless of whether that recipient | ||
118 | # exists. This may turn your mail system into a | ||
119 | # backscatter source: Postfix first accepts mail for | ||
120 | # non-existent recipients and then tries to return | ||
121 | # that mail as "undeliverable" to the often forged | ||
122 | # sender address. | ||
123 | # | ||
124 | # To avoid backscatter with mail for a wild-card | ||
125 | # domain, replace the wild-card mapping with explicit | ||
126 | # 1:1 mappings, or add a reject_unverified_recipient | ||
127 | # restriction for that domain: | ||
128 | # | ||
129 | # smtpd_recipient_restrictions = | ||
130 | # ... | ||
131 | # reject_unauth_destination | ||
132 | # check_recipient_access | ||
133 | # inline:{example.com=reject_unverified_recipient} | ||
134 | # unverified_recipient_reject_code = 550 | ||
135 | # | ||
136 | # In the above example, Postfix may contact a remote | ||
137 | # server if the recipient is aliased to a remote | ||
138 | # address. | ||
139 | # | ||
140 | # RESULT ADDRESS REWRITING | ||
141 | # The lookup result is subject to address rewriting: | ||
142 | # | ||
143 | # o When the result has the form @otherdomain, the | ||
144 | # result becomes the same user in otherdomain. This | ||
145 | # works only for the first address in a multi-address | ||
146 | # lookup result. | ||
147 | # | ||
148 | # o When "append_at_myorigin=yes", append "@$myorigin" | ||
149 | # to addresses without "@domain". | ||
150 | # | ||
151 | # o When "append_dot_mydomain=yes", append ".$mydomain" | ||
152 | # to addresses without ".domain". | ||
153 | # | ||
154 | # ADDRESS EXTENSION | ||
155 | # When a mail address localpart contains the optional recip- | ||
156 | # ient delimiter (e.g., user+foo@domain), the lookup order | ||
157 | # becomes: user+foo@domain, user@domain, user+foo, user, and | ||
158 | # @domain. | ||
159 | # | ||
160 | # The propagate_unmatched_extensions parameter controls | ||
161 | # whether an unmatched address extension (+foo) is propa- | ||
162 | # gated to the result of table lookup. | ||
163 | # | ||
164 | # VIRTUAL ALIAS DOMAINS | ||
165 | # Besides virtual aliases, the virtual alias table can also | ||
166 | # be used to implement virtual alias domains. With a virtual | ||
167 | # alias domain, all recipient addresses are aliased to | ||
168 | # addresses in other domains. | ||
169 | # | ||
170 | # Virtual alias domains are not to be confused with the vir- | ||
171 | # tual mailbox domains that are implemented with the Postfix | ||
172 | # virtual(8) mail delivery agent. With virtual mailbox | ||
173 | # domains, each recipient address can have its own mailbox. | ||
174 | # | ||
175 | # With a virtual alias domain, the virtual domain has its | ||
176 | # own user name space. Local (i.e. non-virtual) usernames | ||
177 | # are not visible in a virtual alias domain. In particular, | ||
178 | # local aliases(5) and local mailing lists are not visible | ||
179 | # as localname@virtual-alias.domain. | ||
180 | # | ||
181 | # Support for a virtual alias domain looks like: | ||
182 | # | ||
183 | # /etc/postfix/main.cf: | ||
184 | # virtual_alias_maps = hash:/etc/postfix/virtual | ||
185 | # | ||
186 | # Note: some systems use dbm databases instead of hash. See | ||
187 | # the output from "postconf -m" for available database | ||
188 | # types. | ||
189 | # | ||
190 | # /etc/postfix/virtual: | ||
191 | # virtual-alias.domain anything (right-hand content does not matter) | ||
192 | # postmaster@virtual-alias.domain postmaster | ||
193 | # user1@virtual-alias.domain address1 | ||
194 | # user2@virtual-alias.domain address2, address3 | ||
195 | # | ||
196 | # The virtual-alias.domain anything entry is required for a | ||
197 | # virtual alias domain. Without this entry, mail is rejected | ||
198 | # with "relay access denied", or bounces with "mail loops | ||
199 | # back to myself". | ||
200 | # | ||
201 | # Do not specify virtual alias domain names in the main.cf | ||
202 | # mydestination or relay_domains configuration parameters. | ||
203 | # | ||
204 | # With a virtual alias domain, the Postfix SMTP server | ||
205 | # accepts mail for known-user@virtual-alias.domain, and | ||
206 | # rejects mail for unknown-user@virtual-alias.domain as | ||
207 | # undeliverable. | ||
208 | # | ||
209 | # Instead of specifying the virtual alias domain name via | ||
210 | # the virtual_alias_maps table, you may also specify it via | ||
211 | # the main.cf virtual_alias_domains configuration parameter. | ||
212 | # This latter parameter uses the same syntax as the main.cf | ||
213 | # mydestination configuration parameter. | ||
214 | # | ||
215 | # REGULAR EXPRESSION TABLES | ||
216 | # This section describes how the table lookups change when | ||
217 | # the table is given in the form of regular expressions. For | ||
218 | # a description of regular expression lookup table syntax, | ||
219 | # see regexp_table(5) or pcre_table(5). | ||
220 | # | ||
221 | # Each pattern is a regular expression that is applied to | ||
222 | # the entire address being looked up. Thus, user@domain mail | ||
223 | # addresses are not broken up into their user and @domain | ||
224 | # constituent parts, nor is user+foo broken up into user and | ||
225 | # foo. | ||
226 | # | ||
227 | # Patterns are applied in the order as specified in the ta- | ||
228 | # ble, until a pattern is found that matches the search | ||
229 | # string. | ||
230 | # | ||
231 | # Results are the same as with indexed file lookups, with | ||
232 | # the additional feature that parenthesized substrings from | ||
233 | # the pattern can be interpolated as $1, $2 and so on. | ||
234 | # | ||
235 | # TCP-BASED TABLES | ||
236 | # This section describes how the table lookups change when | ||
237 | # lookups are directed to a TCP-based server. For a descrip- | ||
238 | # tion of the TCP client/server lookup protocol, see tcp_ta- | ||
239 | # ble(5). This feature is not available up to and including | ||
240 | # Postfix version 2.4. | ||
241 | # | ||
242 | # Each lookup operation uses the entire address once. Thus, | ||
243 | # user@domain mail addresses are not broken up into their | ||
244 | # user and @domain constituent parts, nor is user+foo broken | ||
245 | # up into user and foo. | ||
246 | # | ||
247 | # Results are the same as with indexed file lookups. | ||
248 | # | ||
249 | # BUGS | ||
250 | # The table format does not understand quoting conventions. | ||
251 | # | ||
252 | # CONFIGURATION PARAMETERS | ||
253 | # The following main.cf parameters are especially relevant | ||
254 | # to this topic. See the Postfix main.cf file for syntax | ||
255 | # details and for default values. Use the "postfix reload" | ||
256 | # command after a configuration change. | ||
257 | # | ||
258 | # virtual_alias_maps ($virtual_maps) | ||
259 | # Optional lookup tables that alias specific mail | ||
260 | # addresses or domains to other local or remote | ||
261 | # address. | ||
262 | # | ||
263 | # virtual_alias_domains ($virtual_alias_maps) | ||
264 | # Postfix is final destination for the specified list | ||
265 | # of virtual alias domains, that is, domains for | ||
266 | # which all addresses are aliased to addresses in | ||
267 | # other local or remote domains. | ||
268 | # | ||
269 | # propagate_unmatched_extensions (canonical, virtual) | ||
270 | # What address lookup tables copy an address exten- | ||
271 | # sion from the lookup key to the lookup result. | ||
272 | # | ||
273 | # Other parameters of interest: | ||
274 | # | ||
275 | # inet_interfaces (all) | ||
276 | # The network interface addresses that this mail sys- | ||
277 | # tem receives mail on. | ||
278 | # | ||
279 | # mydestination ($myhostname, localhost.$mydomain, local- | ||
280 | # host) | ||
281 | # The list of domains that are delivered via the | ||
282 | # $local_transport mail delivery transport. | ||
283 | # | ||
284 | # myorigin ($myhostname) | ||
285 | # The domain name that locally-posted mail appears to | ||
286 | # come from, and that locally posted mail is deliv- | ||
287 | # ered to. | ||
288 | # | ||
289 | # owner_request_special (yes) | ||
290 | # Enable special treatment for owner-listname entries | ||
291 | # in the aliases(5) file, and don't split owner-list- | ||
292 | # name and listname-request address localparts when | ||
293 | # the recipient_delimiter is set to "-". | ||
294 | # | ||
295 | # proxy_interfaces (empty) | ||
296 | # The network interface addresses that this mail sys- | ||
297 | # tem receives mail on by way of a proxy or network | ||
298 | # address translation unit. | ||
299 | # | ||
300 | # SEE ALSO | ||
301 | # cleanup(8), canonicalize and enqueue mail | ||
302 | # postmap(1), Postfix lookup table manager | ||
303 | # postconf(5), configuration parameters | ||
304 | # canonical(5), canonical address mapping | ||
305 | # | ||
306 | # README FILES | ||
307 | # Use "postconf readme_directory" or "postconf html_direc- | ||
308 | # tory" to locate this information. | ||
309 | # ADDRESS_REWRITING_README, address rewriting guide | ||
310 | # DATABASE_README, Postfix lookup table overview | ||
311 | # VIRTUAL_README, domain hosting guide | ||
312 | # | ||
313 | # LICENSE | ||
314 | # The Secure Mailer license must be distributed with this | ||
315 | # software. | ||
316 | # | ||
317 | # AUTHOR(S) | ||
318 | # Wietse Venema | ||
319 | # IBM T.J. Watson Research | ||
320 | # P.O. Box 704 | ||
321 | # Yorktown Heights, NY 10598, USA | ||
322 | # | ||
323 | # Wietse Venema | ||
324 | # Google, Inc. | ||
325 | # 111 8th Avenue | ||
326 | # New York, NY 10011, USA | ||
327 | # | ||
328 | # VIRTUAL(5) | ||
diff --git a/rclone/Makefile b/rclone/Makefile new file mode 100644 index 0000000..02a0969 --- /dev/null +++ b/rclone/Makefile | |||
@@ -0,0 +1,23 @@ | |||
1 | # ref: https://rclone.org/googlephotos/ | ||
2 | |||
3 | .ONESHELL: | ||
4 | |||
5 | IMAGE=rclone/rclone:1.58.0 | ||
6 | |||
7 | config: | ||
8 | rclone config | ||
9 | |||
10 | mount.gh-photos: | ||
11 | mkdir -p ~/data/photos | ||
12 | rclone mount photos:media ~/data/photos --allow-non-empty --vfs-cache-mode writes --cache-dir /tmp/rclone | ||
13 | |||
14 | mount.s3.photos: | ||
15 | mkdir -p ~/data/s3.photos | ||
16 | rclone mount s3:topo.photos ~/data/s3.photos --allow-non-empty --vfs-cache-mode writes --cache-dir /tmp/rclone | ||
17 | |||
18 | mount.s3.backup: | ||
19 | mkdir -p ~/data/s3.backup | ||
20 | rclone mount s3:topo.backup /data/s3.backup --allow-non-empty --vfs-cache-mode writes --cache-dir /tmp/rclone | ||
21 | |||
22 | ls: | ||
23 | rclone ls photos:media | ||
diff --git a/smtpd/Makefile b/smtpd/Makefile new file mode 100644 index 0000000..a29254f --- /dev/null +++ b/smtpd/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | all: dkim | ||
2 | sudo mkdir -p /etc/smtpd /etc/mail | ||
3 | sudo ln -sf `pwd`/smtpd.conf /etc/smtpd/smtpd.conf | ||
4 | sudo cp mail/* /etc/mail/ | ||
5 | dkim: | ||
6 | ls /etc/mail/{passwd,dkim.key,dkim.txt} | ||
7 | passwd: | ||
8 | sudo echo $$(id -un):$$(smtpctl encrypt) | ||
diff --git a/smtpd/mail/spam b/smtpd/mail/spam new file mode 100755 index 0000000..3c48717 --- /dev/null +++ b/smtpd/mail/spam | |||
@@ -0,0 +1,11 @@ | |||
1 | #! /bin/bash | ||
2 | |||
3 | SIZE=$(ls --size /tmp/spam | cut -d' ' -f1) | ||
4 | |||
5 | if test $SIZE -gt 10000; then | ||
6 | cat >/tmp/spam | ||
7 | else | ||
8 | cat >>/tmp/spam | ||
9 | fi | ||
10 | |||
11 | true | ||
diff --git a/smtpd/smtpd.conf b/smtpd/smtpd.conf new file mode 100644 index 0000000..e8a5042 --- /dev/null +++ b/smtpd/smtpd.conf | |||
@@ -0,0 +1,47 @@ | |||
1 | # This is the smtpd server system-wide configuration file. | ||
2 | # See smtpd.conf(5) for more information, refs: | ||
3 | # https://man.openbsd.org/smtpd.conf.5 | ||
4 | # https://unixdigest.com/tutorials/arch-linux-mail-server-tutorial-part-2-opensmtpd-dovecot-dkimproxy-and-lets-encrypt.html | ||
5 | |||
6 | # TIPS: Add a new/group vamil for processing dirty stuffs: | ||
7 | # useradd -m -c "Virtual Mail" -d /var/vmail -s /sbin/nologin vmail | ||
8 | |||
9 | # Certificates from Let's Encrypt. | ||
10 | pki mail.topo.tw cert "/etc/mail/ssl/fullchain.cer" | ||
11 | pki mail.topo.tw key "/etc/mail/ssl/mail.topo.tw.key" | ||
12 | |||
13 | # DKIM, command: | ||
14 | # sudo PIPX_HOME=/opt/pipx PIPX_BIN_DIR=/usr/local/bin pipx install --force git+https://github.com/palant/opensmtpd-filters.git | ||
15 | # refs: https://palant.info/2020/11/09/adding-dkim-support-to-opensmtpd-with-custom-filters/ | ||
16 | filter dkimsign proc-exec "/usr/local/bin/dkimsign topo.tw:dkim:/etc/mail/dkim.key" | ||
17 | filter dkimverify proc-exec "/usr/local/bin/dkimverify topo.tw" | ||
18 | filter dkim chain {"dkimsign", "dkimverify"} | ||
19 | |||
20 | # refs: https://man.openbsd.org/table.5 | ||
21 | table passwd file:/etc/mail/passwd | ||
22 | |||
23 | # To also accept external mail over IPv4 or IPv6, | ||
24 | # respectively replace "listen on localhost" with: | ||
25 | # | ||
26 | # listen on 0.0.0.0 | ||
27 | # listen on :: | ||
28 | listen on lo | ||
29 | listen on enp1s0 inet4 hostname "mail.topo.tw" port 25 tls pki mail.topo.tw filter "dkim" | ||
30 | listen on enp1s0 inet4 hostname "mail.topo.tw" port 587 tls-require mask-src pki mail.topo.tw auth-optional <passwd> filter "dkim" | ||
31 | |||
32 | # Allow delivery from local or domain-owned-by-me | ||
33 | action "me" maildir "/home/pham/Maildir" virtual { "@" = "pham" } | ||
34 | match from any for domain "topo.tw" action "me" | ||
35 | match from local for local action "me" | ||
36 | |||
37 | # Allow outgoing emails: authenticated connection only | ||
38 | action "relay" relay | ||
39 | #match from local for any action "relay" | ||
40 | match auth ! from local for any action "relay" | ||
41 | match from local for any action "relay" | ||
42 | |||
43 | # SPAM: deliver spam to custom mda | ||
44 | action "spam" mda "/etc/mail/spam" virtual { "@" = "pham" } | ||
45 | #match from any for rcpt-to "valxxx@megamail.com.br" action "relay" | ||
46 | #match from any for any action "spam" | ||
47 | #match for any reject | ||
diff --git a/ssh/local.conf b/ssh/local.conf new file mode 100644 index 0000000..2e8a19d --- /dev/null +++ b/ssh/local.conf | |||
@@ -0,0 +1,4 @@ | |||
1 | LoginGraceTime 30 | ||
2 | PermitRootLogin no | ||
3 | MaxAuthTries 3 | ||
4 | PasswordAuthentication no | ||
diff --git a/www/.gitignore b/www/.gitignore new file mode 100644 index 0000000..364fdec --- /dev/null +++ b/www/.gitignore | |||
@@ -0,0 +1 @@ | |||
public/ | |||
diff --git a/www/Makefile b/www/Makefile new file mode 100644 index 0000000..80b9d47 --- /dev/null +++ b/www/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | .ONESHELL: | ||
2 | ROOT_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) | ||
3 | |||
4 | # build html files for public/ | ||
5 | build: | ||
6 | @input_dir=~/log/posts \ | ||
7 | output_dir=/srv/http \ | ||
8 | assets_dir=$(ROOT_DIR)assets \ | ||
9 | template_dir=$(ROOT_DIR)templates \ | ||
10 | $(ROOT_DIR)scripts/build.sh | ||
11 | |||
12 | # Migrage frontmatter from '---' to HTML comment '<!-- -->' | ||
13 | frontmatter: | ||
14 | find content -type f -name '*.md' | xargs sed -i ':frontmatter { 1s/^---/<!--/; 1!s/^---/-->/; 1!b}; /^---/ {1b frontmatter}' | ||
diff --git a/www/assets/favicon.ico b/www/assets/favicon.ico new file mode 100644 index 0000000..5af1857 --- /dev/null +++ b/www/assets/favicon.ico | |||
Binary files differ | |||
diff --git a/www/assets/gpg.asc b/www/assets/gpg.asc new file mode 100644 index 0000000..f33181e --- /dev/null +++ b/www/assets/gpg.asc | |||
@@ -0,0 +1,84 @@ | |||
1 | -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
2 | |||
3 | mQGNBGAzCdIBDACvt2iu+FTg+p3Q5p/J8Q7643g61n3kgIgDt9a5JU06nwAGDmX+ | ||
4 | hIrVy5OxsTntJzRkvV+nr0cR9Suvkci9RfJ9TixjMca+Eld3pPLhdPGmtPofjCaj | ||
5 | LpKMkPdHg+VU4B7BANwsd/on7VYLq5Ko6dj1HKrp3KJappP5njK1u39DQHjLPEjK | ||
6 | 976nyErOdKNVjswIWdLFJgWhC46mH3zW4aOtkw8UIn32fbCmpZyuVU8ooJTbIl6+ | ||
7 | YvU9BsYRgEhSjQbi+RXQZAyUqsQlZnS8/81pwanKs6NFqBSTFaryHVfbC1McXHNY | ||
8 | V3+Y/rGEmUIn2FXhHWWHb8b5oBroZQLbHVpjWV3DZgkTN0c8g+K3hQ1iLFAdWuQg | ||
9 | wxBuzkq/5AMiqJ/0gUjkT4uW12fIEQR30wvveVDq/BMWdhC4tgy+ft5QcBjA3xj2 | ||
10 | xC813/r3cvgfWaJvB5/mUH4QPv1gESG9QdjAVOBMt/TTnKJFes5iuq1q0+ZdnG0S | ||
11 | KZ1aFlfbGgZWcW8AEQEAAbQvdHlwZWJyb29rIDx0eXBlYnJvb2tAZ21haWwuY29t | ||
12 | PiAoR21haWwgQWNjb3VudCmJAdQEEwEIAD4WIQQSgUZMDGWhjNgJ9OxmRzq+mhjP | ||
13 | LQUCYEnKDgIbAwUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRBmRzq+ | ||
14 | mhjPLe7zC/9/6O4+icJc74Y/d/VhJv4k/Zc3b2ZlMrdGq/FDQTYSISPPo2k6hgcS | ||
15 | IQw2SPNb0hRkoaj7Dj3tMFzumSrGMyfGNXHThYWh3UABSTkTnYIXMNhd+on7VpfZ | ||
16 | FqkBrIfgv+Im7Gops66L7x9b3BT16yxb373uG9bhe+w/Kzk8Mix6f57M9f21f/MI | ||
17 | trOKbA50HG6scpmytJ5YHiu7qZVihhVewJDX32e9W9fpMu3Kos+SCDOzxIrLl8An | ||
18 | /8WrSTqAMh/RGYKaxL6A+JjZyhDMXjWMZfvCPfzFrfF60D3ppcDtatqYvMk76i+c | ||
19 | QW8Oiyv8CRWEK9CzSXptz/MsDwzVKn4UV4QFyoCmB4EGLB7+lbSbnNdtZeluoElG | ||
20 | +HKIwayJ9s09m3AItTIoyaejjLp7+NgivoUWueW8c2z4KHSY9uJYij0+3k9VASfx | ||
21 | Njs7DdiWcgezi4BIHS0dC7sRLmJ2U5Bt0oHyRzoDa67trumCLKc/b8xAEaZZCO8z | ||
22 | 5FkhOSquTNe0HUhzaWVoIENoaW4gRmFuIDxwaGFtQHRvcG8udHc+iQHUBBMBCAA+ | ||
23 | FiEEEoFGTAxloYzYCfTsZkc6vpoYzy0FAmIPAUsCGwMFCQPCZwAFCwkIBwIGFQoJ | ||
24 | CAsCBBYCAwECHgECF4AACgkQZkc6vpoYzy0ysQv9FlY6c8Jq5pIFn9i6Jk7a0Pm+ | ||
25 | qmWNwh9t+Wgqv+D7hIrThi9Ldb8VdslJZVGi9rqh1GHIC+lv17yclXQJ+0RHuOo6 | ||
26 | u7EoubT4+xuPWBQGLqcACX0LJO+XBbiN0mTs/7G7U4TOz77PoqRqUVc/mspK97l8 | ||
27 | aqRMXWlA6BKR5iFZLsmgI0i6pQ+YUiZbOEquVpTeRZNJF3aNi7TaZ2fROnlIVAmo | ||
28 | dL0vuypVOLUqFmsiSoqR9V9n31m2LJXDGghh18VAT0hiZh2BCs3mUVwPT9G03naC | ||
29 | nzidrNp/W1y3VU8f5jBdtpCrkQcCN5aIV8BAV6sUEhlezCcdx0YXmms1T6C2I7Ke | ||
30 | fnnFs6M9X32uparkESUGT9DBG/e9whQCGrXeTtn1bEon+HeanWJ/eZZxNNAUFPaX | ||
31 | jNgpl/Gk6zSaLiXi3PFn629piTcalbljn2pbIxwCZWX+Zh800+jRyfs9qCMhcJK2 | ||
32 | J+aVn9+HSGbgwKHB1V/RCVds+WzYIjdujKl2uUr1uQGNBGAzCdIBDADL1lLG8WzO | ||
33 | 8V46ic24UIF2JT2U4A1gfbjJ+vPdKxPxvqrctd54fGcsE8nLhdmiPfodxMwkD6qa | ||
34 | FX0GQz7UmxPNl3k/i74NlTB9G0difp+Pc2fbhYD2nPOanFx3RMxX6df7V4lAlddX | ||
35 | LQ0x0ryt1p8TMLUz38v+ge8oN7au0R4cHpB2ELHaNgpLc/m45XP5Qg02gYDBlO0K | ||
36 | 2ejW/vxpB91LNoRmlozsO+d67MQTX2Gv2mDYIf3L91uHNzbiI7V2V+R2zFkVW11p | ||
37 | 9YKbD5RrC7frD3CZE5wEeFmwAE6z7ivasv7qiNk8+uneIjq13xS8ul5sEbHCuyO1 | ||
38 | XUQ6+KXFMI5djqcoqR1p0C3daozqOygI/QVaV38RJ4XAbNUtL9bv2HjhiuVbbpKU | ||
39 | frQ+7pScQosaF8rszXmr60GwK5SRICfzKTzug7m8Am+8WubjuF5jUC2WMLjMZgBP | ||
40 | WiKtatoMXB4DBAdn4uN/I9IsyE+cZFgo0+Gwr7lCn+6nyYZGQhDR3fcAEQEAAYkB | ||
41 | vAQYAQgAJhYhBBKBRkwMZaGM2An07GZHOr6aGM8tBQJgMwnSAhsMBQkDwmcAAAoJ | ||
42 | EGZHOr6aGM8tWMQMAKD8a0n9MRIb34/6TECJbQ/VIfKiRDhd+vwoGDLoBHGzWcbU | ||
43 | mQPmi3WPVBPpcxihqZi1gFoDLegv4ZFSQKLQOG5+czkLFtwbQCkJizyJFyvT8YtQ | ||
44 | Dr+muBSYWnmPrJbe88qcr2HWNyYkwk0/Ibj8DfQughcSjSq0o2rV8FIITs3Fh8PJ | ||
45 | 55ueOX8hwTBQOS+7LZz9R1RV4d4mxlycv/C8Injx3AkHTcAzivdlaXwD2tO+3gVn | ||
46 | 2+oi9NFRL7esI+9jk1jCVHZjBISQ6KevxAYJW7+rE90AEBmgfeNXwWKA924mlkUP | ||
47 | wxeBxFEOFySH06mfXYC9//wtOL6cmKV8xrhjAOnvLrXC/ILjzxBox+s/82pnUfSL | ||
48 | ciR+TOTLVAWfB7Ep0qhrOueOXhD7eLf4Ald2Pd1/xSlQfRhMirjCL2dJ1tbx4nZP | ||
49 | h+24fDXiw1zyumY5d5CbjB9/LKXMdwVhNW1CpP8Tw8oFgKbTuJMQgYQBNX6OnJRj | ||
50 | 4Cdkkud6LseLjVF9IbkCDQRh1Tq6ARAA6swAJeTtdlE4L8OygVprgTc3uvzoHfLh | ||
51 | UfNlVxMwXeO75CEPXaovZs08c61vue4BgMxpDb7uxkBbnjTW1E3vtG2MLKJ0jHt3 | ||
52 | ZuqPFgzHqxmqDgces12jDlITcYK15RxJdrdEjeDDziwKo/v64aY2RDRLk1brJxYb | ||
53 | DMB1Mjcgwr1GZd8CsoR4rA9YWBB49b1XdmEM/ra3vutBJFa/PmFTVz9v3NCf9g40 | ||
54 | +k4eMTsb4RfG5mL2nk7DH+iJWw110Nk3IDhKLlxNIAPA1v6HQ5k3yvU/cwQtE7UA | ||
55 | OyXQOnJPYMyzGFvcscD04GO9D23JAKLc7R9vk/77m4n3qI8IRZNVaQbAFax6wx7M | ||
56 | LXg5jsgCmOESljfquUYricuieefZExWJueJedK6nHrMeqr1b9GV2SFJumN7XNZ2u | ||
57 | fYP3lm5FkutPQFSqLhLD9wlqGNxyZMNAxy2smAsI8V7a7OwJdl9sugs+Tz+lHYSW | ||
58 | o6PGhAUqFYXFknWlarEOlXrUtv18m8JnsMXrjWTajhlaxsgLFrpi8Li+aY/LN/YN | ||
59 | 7Jw0uWK4EQE6oebK8at4u9ChndaqLoyevUZ0LdTH7Fv7bnhSMk+4igrX3dVZv560 | ||
60 | I908Oz2ncI+eAvzlIGudk9bEL9lf/aQlVLs+aDG7Q3xhQX+rbNNOJgnTToW6oyzJ | ||
61 | sOoWAuhEf40AEQEAAYkD8gQYAQgAJhYhBBKBRkwMZaGM2An07GZHOr6aGM8tBQJh | ||
62 | 1Tq6AhsCBQkB4TOAAkAJEGZHOr6aGM8twXQgBBkBCAAdFiEEcXjol+7uC8jTh2ia | ||
63 | UN6fYpttz1kFAmHVOroACgkQUN6fYpttz1kZxQ//dvupgSMMzC1Un9VbvB5kIuPD | ||
64 | +6mYQGCs8bc7FY1ZsOKQdeZnR3sqpEvSiZI+i/sD436D/1xAf43c2uSPzK18g1N5 | ||
65 | qXax+eKlZPMGrdbVO2TjSfg0Fhz8y9ckH7u4Rb123VOurAfDrXJzmUtCChNu3iA/ | ||
66 | IcH9t7z8vDj91/yaW5MjgmQgijL7XC57dClu03YM3rjdQmaFXbxeGGq72NPdPjLz | ||
67 | heCgjMEoUJ8viQqOBiM+BIMjftvfsyPQjELOOQTy+TeU/Yu9JTzVTntjVyBlz4Y7 | ||
68 | vCqfxnmEu3qsHayKYPVgCKatrP4OmqsW61kup3itcxlfq5C21WL0xJLUPq3NYOwl | ||
69 | FX+3ufcfy7TrS7BcNYvfPbvIrNW10l2GTHIvjqla7wfP4+Zo47KuxYRvDFD6I21P | ||
70 | Fx3/4JQfShXx0WiO1mgpA8CH2P8ZDPcdMl9Q8N8DZUHU6ClEfrMLEYGzupfSPcJH | ||
71 | +6sGuopfIVJ0GOHvsfZarcBqJsY3QG9lLMSAGslA7uFLoD3Wl/0ecMgDY3HuI11v | ||
72 | aecZCJTs5JzIrzye2FZS73h/6yY7HNY4PEtfFoOrGY4jiugRnu9RLXc1/HgR/Veb | ||
73 | mXPuueTwqiTMiSC81kAIEuSjTiePlmVX/d8Bm4KYQN6Ey0H4yW+TdSTeuRv1CkCe | ||
74 | bpj5dum8whxqNw+GoClCcgv/fD3TPNddQFG6Agrk6dj5LlwZc5KuYSTmRlX2hNiP | ||
75 | u9/wWO0oJFsqUYTe6h1wrZDinXwoiIWfeEZSQKzq3LgxkkzAy9LebGjXlX51eN8X | ||
76 | 3rgWtWGeaq1VlYHeDXSDhCAXzVAo3bRAp37H7GDIscitL35umPudfP/FTOvYJmNL | ||
77 | rx1cbd0yTrxgAhAm1+Tx9BWyDb3dnfZPBkHxyrND1RmJQN0kMEnnjvhdRefZXcWf | ||
78 | 53RRiHXjpZ2mXwW6eNAwGuadgcXjvgb3Nb0ZsLHlu1XBOx8pvxoKJtNIi0+1RoRm | ||
79 | juSV8BDPIaIMPn/xlR2E0a3Hft3L8Y4xZXj0DBnYncd2prLiihJezA7CqCRFO1+l | ||
80 | 7y9ZFEdx9sVrlT/5oWcQ6rLMt0ImiOOaGZYntDMKywtqy4p27lplZPbzj1wBEHGQ | ||
81 | ukVHh7WOTesLHslm3q0mCfYFJPpMxpB6KsSq37zY4Pni1ByC+p2V1S6VcjT0WFmw | ||
82 | RWr5Ni7wyLHOaHhoDLK9i+Fz | ||
83 | =DNGE | ||
84 | -----END PGP PUBLIC KEY BLOCK----- | ||
diff --git a/www/assets/robots.txt b/www/assets/robots.txt new file mode 100644 index 0000000..41f82c4 --- /dev/null +++ b/www/assets/robots.txt | |||
@@ -0,0 +1,4 @@ | |||
1 | User-agent: * | ||
2 | Allow: / | ||
3 | |||
4 | Sitemap: https://topo.tw/sitemap.xml | ||
diff --git a/www/assets/style.css b/www/assets/style.css new file mode 100644 index 0000000..2752323 --- /dev/null +++ b/www/assets/style.css | |||
@@ -0,0 +1,213 @@ | |||
1 | header { | ||
2 | display: flex; | ||
3 | justify-content: space-between; | ||
4 | margin-top: 1rem; | ||
5 | } | ||
6 | |||
7 | footer * { | ||
8 | display: inline; | ||
9 | } | ||
10 | |||
11 | blockquote { | ||
12 | color: gray; | ||
13 | font-size: 1.2rem; | ||
14 | font-style: italic; | ||
15 | |||
16 | text-align: center; | ||
17 | } | ||
18 | |||
19 | p code { | ||
20 | margin-inline: 0.2rem; | ||
21 | padding-inline: 6px; | ||
22 | } | ||
23 | |||
24 | /* Neat CSS: https://neat.joeldare.com */ | ||
25 | * { | ||
26 | box-sizing: border-box; | ||
27 | } | ||
28 | |||
29 | :root { | ||
30 | color-scheme: light dark; | ||
31 | --light: #fff; | ||
32 | /* --light: #f7f7f7; */ | ||
33 | --lesslight: #efefef; | ||
34 | --dark: #404040; | ||
35 | --moredark: #000; | ||
36 | /*--link: royalblue; */ | ||
37 | --link: #850000; | ||
38 | --link-highlight-color: #ffdcda; | ||
39 | /* border-top: 5px solid var(--dark); */ | ||
40 | line-height: 1.5em; | ||
41 | font-family: system-ui, sans-serif; | ||
42 | font-size: 16px; | ||
43 | color: var(--dark); | ||
44 | } | ||
45 | |||
46 | h1 { | ||
47 | line-height: 1em; | ||
48 | } | ||
49 | |||
50 | button, input { | ||
51 | font-size: 1em; /* Override browser default font shrinking*/ | ||
52 | } | ||
53 | |||
54 | input { | ||
55 | border: 1px solid var(--dark); | ||
56 | background-color: var(--lesslight); | ||
57 | border-radius: .25em; | ||
58 | padding: .5em; | ||
59 | } | ||
60 | |||
61 | pre { | ||
62 | background-color: var(--lesslight); | ||
63 | margin: 0.5em 0 0.5em 0; | ||
64 | padding: 0.5em; | ||
65 | overflow: auto; | ||
66 | } | ||
67 | |||
68 | code { | ||
69 | background-color: var(--lesslight); | ||
70 | } | ||
71 | |||
72 | body { | ||
73 | background-color: var(--light); | ||
74 | margin: 0; | ||
75 | max-width: 800px; | ||
76 | padding: 0 20px 20px 20px; | ||
77 | margin-left: auto; | ||
78 | margin-right: auto; | ||
79 | } | ||
80 | |||
81 | a { | ||
82 | outline: none; | ||
83 | text-decoration: underline 2px var(--link-highlight-color); | ||
84 | color: var(--link); | ||
85 | } | ||
86 | |||
87 | a:hover { | ||
88 | background: var(--link-highlight-color); | ||
89 | } | ||
90 | |||
91 | img { | ||
92 | max-width: 100%; | ||
93 | height: auto; | ||
94 | } | ||
95 | |||
96 | button, .button, input[type=submit] { | ||
97 | display: inline-block; | ||
98 | background-color: var(--dark); | ||
99 | color: var(--light); | ||
100 | text-align: center; | ||
101 | padding: .5em; | ||
102 | border-radius: .25em; | ||
103 | text-decoration: none; | ||
104 | border: none; | ||
105 | cursor: pointer; | ||
106 | } | ||
107 | |||
108 | button:hover, .button:hover, input[type=submit]:hover { | ||
109 | color: var(--lesslight); | ||
110 | background-color: var(--moredark); | ||
111 | } | ||
112 | |||
113 | /* Add a margin between side-by-side buttons */ | ||
114 | button + button, .button + .button, input[type=submit] + input[type=submit] { | ||
115 | margin-left: 1em; | ||
116 | } | ||
117 | |||
118 | .center { | ||
119 | display: block; | ||
120 | margin-left: auto; | ||
121 | margin-right: auto; | ||
122 | text-align: center; | ||
123 | } | ||
124 | |||
125 | .bordered { | ||
126 | border: 3px solid; | ||
127 | } | ||
128 | |||
129 | .home { | ||
130 | display: inline-block; | ||
131 | background-color: var(--dark); | ||
132 | color: var(--light); | ||
133 | margin-top: 20px; | ||
134 | padding: 5px 10px 5px 10px; | ||
135 | text-decoration: none; | ||
136 | font-weight: bold; | ||
137 | } | ||
138 | |||
139 | |||
140 | /* Desktop sizes */ | ||
141 | @media (min-width: 600px) { | ||
142 | ol.twocol { | ||
143 | column-count: 2; | ||
144 | } | ||
145 | |||
146 | .row { | ||
147 | display: flex; | ||
148 | flex-direction: row; | ||
149 | padding: 0; | ||
150 | width: 100%; | ||
151 | } | ||
152 | |||
153 | /* Make everything in a row a column */ | ||
154 | .row > * { | ||
155 | display: block; | ||
156 | flex: 1 1 auto; | ||
157 | max-width: 100%; | ||
158 | width: 100%; | ||
159 | } | ||
160 | |||
161 | .row > *:not(:last-child) { | ||
162 | margin-right: 10px; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | /* Dark mode overrides (confusingly inverse) */ | ||
167 | @media (prefers-color-scheme: dark) { | ||
168 | :root { | ||
169 | --light: #222; | ||
170 | --lesslight: #333; | ||
171 | --dark: #eee; | ||
172 | --moredark: #fefefe; | ||
173 | } | ||
174 | /* This fixes an odd blue then white shadow on FF in dark mode */ | ||
175 | *:focus { | ||
176 | outline: var(--light); | ||
177 | box-shadow: 0 0 0 .25em var(--link); | ||
178 | } | ||
179 | } | ||
180 | |||
181 | /* Printing */ | ||
182 | @media print { | ||
183 | .home { | ||
184 | display: none; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | [data-tooltip]{ | ||
189 | display: inline-block; | ||
190 | position: relative; | ||
191 | |||
192 | &::after { | ||
193 | display: block; | ||
194 | position: absolute; | ||
195 | content: attr(data-tooltip); | ||
196 | background: var(--dark); | ||
197 | color: var(--lesslight); | ||
198 | padding: .25em; | ||
199 | cursor: default; | ||
200 | user-select: text; | ||
201 | |||
202 | transition: | ||
203 | visibility .3s ease-out, | ||
204 | opacity .3s ease-out; | ||
205 | visibility: hidden; | ||
206 | opacity: 0; | ||
207 | } | ||
208 | |||
209 | &:hover::after { | ||
210 | opacity: 1; | ||
211 | visibility: visible; | ||
212 | } | ||
213 | } | ||
diff --git a/www/assets/wp-admin.php b/www/assets/wp-admin.php new file mode 100644 index 0000000..b774c98 --- /dev/null +++ b/www/assets/wp-admin.php | |||
@@ -0,0 +1 @@ | |||
Got you! | |||
diff --git a/www/scripts/add-graph.py b/www/scripts/add-graph.py new file mode 100755 index 0000000..455b45a --- /dev/null +++ b/www/scripts/add-graph.py | |||
@@ -0,0 +1,35 @@ | |||
1 | #! /bin/python3 | ||
2 | |||
3 | import sys, subprocess | ||
4 | from datetime import date | ||
5 | from bs4 import BeautifulSoup | ||
6 | |||
7 | def handle(html): | ||
8 | soup = BeautifulSoup(html, 'html.parser') | ||
9 | for graph in soup.select('pre.language-graph'): | ||
10 | print() | ||
11 | print(date.today().strftime("%H:%M:%S")) | ||
12 | print('before:') | ||
13 | print(graph.string) | ||
14 | |||
15 | process = subprocess.Popen( | ||
16 | ["/usr/bin/vendor_perl/graph-easy", "--boxart"], | ||
17 | stdin=subprocess.PIPE, | ||
18 | stdout=subprocess.PIPE, | ||
19 | stderr=subprocess.PIPE | ||
20 | ) | ||
21 | output, error = process.communicate(input=graph.get_text().encode()) | ||
22 | graph.string = output.decode() | ||
23 | |||
24 | print('After:') | ||
25 | print(graph.string) | ||
26 | print('Error:') | ||
27 | print(error.decode()) | ||
28 | return str(soup) | ||
29 | |||
30 | for line in sys.stdin: | ||
31 | file = line.rstrip("\n") | ||
32 | with open(file, 'r') as html: | ||
33 | new_content = handle(html) | ||
34 | with open(file, 'w') as html: | ||
35 | html.write(new_content) | ||
diff --git a/www/scripts/build.sh b/www/scripts/build.sh new file mode 100755 index 0000000..9b95c99 --- /dev/null +++ b/www/scripts/build.sh | |||
@@ -0,0 +1,188 @@ | |||
1 | #! /bin/bash | ||
2 | |||
3 | set -e | ||
4 | |||
5 | # Executable command for markdown | ||
6 | markdown_bin="markdown -f fencedcode,autolink,alphalist,autolink,footnote" | ||
7 | |||
8 | # Directory for input/output | ||
9 | input_dir=${input_dir:?ENV \"input_dir\" is not set} | ||
10 | output_dir=${output_dir:?ENV \"output_dir\" is not set} | ||
11 | assets_dir=${assets_dir:?ENV \"assets_dir\" is not set} | ||
12 | template_dir=${template_dir:?ENV \"template_dir\" is not set} | ||
13 | |||
14 | # functions {{{ | ||
15 | |||
16 | # add indent for each line except <pre> | ||
17 | indent() { | ||
18 | indent="$(printf "%${1}s")" | ||
19 | sed "s/^/${indent}/; /<pre>/!b; :pre; N; /<\/pre>/!b pre" | ||
20 | } | ||
21 | |||
22 | # use heredoc to generate html from .md file and templates | ||
23 | html() { | ||
24 | <<-END_OF_HTML sed '1d;$d' | ||
25 | |||
26 | <!DOCTYPE html> | ||
27 | <html lang="en"> | ||
28 | ${head} | ||
29 | <body> | ||
30 | ${header} | ||
31 | <hr><br> | ||
32 | <main> | ||
33 | $(${markdown_bin} | indent 4) | ||
34 | </main> | ||
35 | <br><hr> | ||
36 | ${footer} | ||
37 | </body> | ||
38 | </html> | ||
39 | |||
40 | END_OF_HTML | ||
41 | } | ||
42 | |||
43 | # list of latest posts in markdown format | ||
44 | latest_posts() { | ||
45 | (IFS=$'\n'; echo "${index_list[*]}") | sort -r | head -20 | while read date path title; do | ||
46 | echo "- <time datetime="$date">$date</time> [$title](/$path)" | ||
47 | done | ||
48 | } | ||
49 | |||
50 | # print frontmatter from markdown file with format: "<key> <value>" | ||
51 | get_frontmatter() { | ||
52 | sed -n '1 {/<!--/ !q; n}; /-->/q; s/"//g; s/://p' | ||
53 | } | ||
54 | |||
55 | # process frontmatter | ||
56 | add_index() { | ||
57 | unset title public index date draft | ||
58 | |||
59 | # define local variables for frontmatter | ||
60 | while read key value; do | ||
61 | local -r $key="$value" | ||
62 | done <<<"$(get_frontmatter)" | ||
63 | |||
64 | # don't process draft after function call | ||
65 | test "$draft" != "" && return 1 | ||
66 | |||
67 | # skip making index in some cases | ||
68 | test "$public" = false && return 0 | ||
69 | test "$index" = false && return 0 | ||
70 | test "$type" = demo && return 0 | ||
71 | test "$title" = "" && return 0 | ||
72 | iso8601=$(date --iso --date "${date:-NULL}" 2>/dev/null) | ||
73 | test "$iso8601" = "" && return 0 | ||
74 | |||
75 | # put frontmatter info into variable "index" if title and date are valid | ||
76 | index_list+=("$iso8601 $path $title") | ||
77 | } | ||
78 | |||
79 | # remove SGML comments but keep the top one as frontmatter | ||
80 | ignore_comment() { | ||
81 | sed '1 !{ /^<!--$/,/^-->$/ d }' | ||
82 | } | ||
83 | |||
84 | # Generate the feed file | ||
85 | make_rss() { | ||
86 | echo -n "Making RSS " | ||
87 | |||
88 | rssfile=$blog_feed.$RANDOM | ||
89 | while [[ -f $rssfile ]]; do rssfile=$blog_feed.$RANDOM; done | ||
90 | |||
91 | { | ||
92 | pubdate=$(LC_ALL=C date +"$date_format_full") | ||
93 | cat <<-EOF | ||
94 | <?xml version="1.0" encoding="UTF-8" ?>' | ||
95 | <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">' | ||
96 | <channel><title>Dummy Website</title><link>https://topo.tw/index.xml</link>" | ||
97 | <description>$global_description</description><language>en</language>" | ||
98 | <lastBuildDate>$pubdate</lastBuildDate>" | ||
99 | <pubDate>$pubdate</pubDate>" | ||
100 | <atom:link href="$global_url/$blog_feed" rel="self" type="application/rss+xml" />" | ||
101 | EOF | ||
102 | |||
103 | n=0 | ||
104 | while IFS='' read -r i; do | ||
105 | is_boilerplate_file "$i" && continue | ||
106 | ((n >= number_of_feed_articles)) && break # max 10 items | ||
107 | echo -n "." 1>&3 | ||
108 | echo '<item><title>' | ||
109 | get_post_title "$i" | ||
110 | echo '</title><description><![CDATA[' | ||
111 | get_html_file_content 'text' 'entry' $cut_do <"$i" | ||
112 | echo "]]></description><link>$global_url/${i#./}</link>" | ||
113 | echo "<guid>$global_url/$i</guid>" | ||
114 | echo "<dc:creator>$(get_post_author "$i")</dc:creator>" | ||
115 | echo "<pubDate>$(LC_ALL=C date -r "$i" +"$date_format_full")</pubDate></item>" | ||
116 | |||
117 | n=$(( n + 1 )) | ||
118 | done < <(ls -t ./*.html) | ||
119 | |||
120 | echo '</channel></rss>' | ||
121 | } 3>&1 >"$rssfile" | ||
122 | echo "" | ||
123 | |||
124 | mv "$rssfile" "$blog_feed" | ||
125 | chmod 644 "$blog_feed" | ||
126 | } | ||
127 | |||
128 | # }}} | ||
129 | # prepare directory for outputs {{{ | ||
130 | |||
131 | mkdir -p $output_dir/ | ||
132 | rm -rf $output_dir/** | ||
133 | ln -s $assets_dir/* $output_dir/ | ||
134 | |||
135 | # }}} | ||
136 | # content of templates {{{ | ||
137 | |||
138 | head="$(cat $template_dir/head.html)" | ||
139 | header="$(cat $template_dir/header.html | indent 2)" | ||
140 | footer="$(cat $template_dir/footer.html | indent 2)" | ||
141 | index_list=() | ||
142 | index_template="$(cat $template_dir/index.md)" | ||
143 | |||
144 | # }}} | ||
145 | # for each markdown file {{{ | ||
146 | |||
147 | files="$(find "$input_dir" -type f -name '*md')" | ||
148 | total=$(wc -l <<<"$files") | ||
149 | declare -i counter | ||
150 | for file in $files; do | ||
151 | # set variables | ||
152 | path=$(<<<"$file" sed "s#^${input_dir}/##; s/\.md$//").html; mkdir -p $(dirname $output_dir/$path) | ||
153 | content="$(cat ${file} | ignore_comment)" | ||
154 | |||
155 | # use frontmatter to decide making html file or not | ||
156 | <<<"$content" add_index || continue | ||
157 | |||
158 | # log | ||
159 | echo -e "\033[1K\r$((counter+=1))/$total \t\t processing $path" | ||
160 | |||
161 | # make html file for draft | ||
162 | h1="$(<<<"$content" get_frontmatter | sed -n 's/^title *//p')" | ||
163 | echo "$content" \ | ||
164 | | tee $output_dir/${file#${input_dir}/} \ | ||
165 | | { [ -n "$h1" ] && echo "# $h1"; cat; } \ | ||
166 | | html >$output_dir/$path | ||
167 | done | ||
168 | echo | ||
169 | |||
170 | # }}} | ||
171 | # make index.html {{{ | ||
172 | |||
173 | { | ||
174 | echo "${index_template}" | ||
175 | echo -e '<br><br>\n\n' | ||
176 | latest_posts | ||
177 | } \ | ||
178 | | tee $output_dir/index.md \ | ||
179 | | html >$output_dir/index.html | ||
180 | |||
181 | echo -e index.html "\t" generated | ||
182 | |||
183 | # }}} | ||
184 | # make index.xml {{{ | ||
185 | |||
186 | |||
187 | |||
188 | # }}} | ||
diff --git a/www/templates/footer.html b/www/templates/footer.html new file mode 100644 index 0000000..9e87e02 --- /dev/null +++ b/www/templates/footer.html | |||
@@ -0,0 +1,4 @@ | |||
1 | <footer> | ||
2 | <address><a href="mailto:info@topo.tw">info@topo.tw</a></address> | | ||
3 | <a href="http://creativecommons.org/publicdomain/zero/1.0" rel="license noopener noreferrer">CC0 1.0</a> | ||
4 | </footer> | ||
diff --git a/www/templates/head.html b/www/templates/head.html new file mode 100644 index 0000000..ede99c9 --- /dev/null +++ b/www/templates/head.html | |||
@@ -0,0 +1,10 @@ | |||
1 | <head> | ||
2 | <meta charset="UTF-8"> | ||
3 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
4 | <meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||
5 | |||
6 | <title>Dummy Site</title> | ||
7 | |||
8 | <link rel="stylesheet" href="/style.css"> | ||
9 | <link rel="icon" href="/favicon.ico" type="image/x-icon"> | ||
10 | </head> | ||
diff --git a/www/templates/header.html b/www/templates/header.html new file mode 100644 index 0000000..a77079a --- /dev/null +++ b/www/templates/header.html | |||
@@ -0,0 +1,17 @@ | |||
1 | <header> | ||
2 | <nav class="left"> | ||
3 | <a href="/">Home</a> | | ||
4 | <a href="/about.html" data-tooltip="About this site">About</a> | | ||
5 | <a href="/posts/">Posts</a> | | ||
6 | <a href="/projects.html" data-tooltip="Not valid now...">Projects</a> | | ||
7 | <!-- | ||
8 | <a href="/links.html" data-tooltip="Cool sites you might be interested">Links</a> | ||
9 | --> | ||
10 | <a href="/links.html" data-tooltip="Not valid now...">Links</a> | ||
11 | </nav> | ||
12 | <nav class="right"> | ||
13 | <a href="/rss.xml" data-tooltip="Not valid now...">RSS</a> | | ||
14 | <a href="https://git.topo.tw" data-tooltip="Public Git Repos">Code</a> | | ||
15 | <a href="/gpg.asc">GPG</a> | ||
16 | </nav> | ||
17 | </header> | ||
diff --git a/www/templates/index.md b/www/templates/index.md new file mode 100644 index 0000000..5743a19 --- /dev/null +++ b/www/templates/index.md | |||
@@ -0,0 +1 @@ | |||
> There should be a intro for this site, but I cannot came up with any idea about this... | |||