|
1 http://redmine.lighttpd.net/projects/1/wiki/HowToSetupFastCgiIndividualPermissions |
|
2 |
|
3 1. Add users to the operating system |
|
4 |
|
5 (This is only needed if you haven't added users yet.) |
|
6 |
|
7 You must add a user account to the operating system for each user that you want |
|
8 to give separate user permissions, in order to deny access to other users' |
|
9 source code. |
|
10 |
|
11 2. Add user groups to the operating system |
|
12 |
|
13 You need to add one user group for each user added above. To keep things |
|
14 simple, we just name the user groups similar: |
|
15 |
|
16 Now you need to add users to each of these user groups. For each user group, |
|
17 there must be two members: the corresponding user and the lighttpd daemon user. |
|
18 |
|
19 You configure the user groups by editing /etc/group with your favourite text editor. |
|
20 |
|
21 The file must look something like this (group numbers may vary): |
|
22 |
|
23 ..... [lots of stuff above] |
|
24 fred:x:441:fred,lighttpd |
|
25 george:x:442:george,lighttpd |
|
26 ron:x:443:ron,lighttpd |
|
27 |
|
28 You might also use a sed command like this: |
|
29 |
|
30 sed -i "s/^\(fred.*\)$/\1,fred,lighttpd/g" /etc/group |
|
31 sed -i "s/^\(george.*\)$/\1,george,lighttpd/g" /etc/group |
|
32 sed -i "s/^\(ron.*\)$/\1,ron,lighttpd/g" /etc/group |
|
33 |
|
34 These commands add the user and the lighttpd user to the groups. |
|
35 |
|
36 3. Set up filesystem structure |
|
37 |
|
38 Let's assume that you want to keep all files associated with the web-server's |
|
39 virtual hosts under the directory ''/var/www''. (Of course you can choose |
|
40 another location, just make sure that the users created above have read and |
|
41 execute rights to the directory. (I.e. ''chmod 755 /var/www && chown root:root |
|
42 /var/www''). |
|
43 |
|
44 3.1 Create server root directory |
|
45 |
|
46 Now, create two directories: One for some start-up scripts that only root have |
|
47 access to, and another for all your virtual hosts: |
|
48 |
|
49 #!ShellExample |
|
50 # cd /var/www |
|
51 # mkdir fastcgi |
|
52 # mkdir vhosts |
|
53 # chown lighttpd:lighttpd * |
|
54 # chmod 755 * |
|
55 |
|
56 # ls -l /var/www |
|
57 |
|
58 drwxr-xr-x 2 lighttpd lighttpd 4096 Feb 15 12:17 fastcgi |
|
59 drwxr-xr-x 9 lighttpd lighttpd 4096 Feb 15 11:21 vhosts |
|
60 |
|
61 3.2 Create a directory for each virtual host |
|
62 |
|
63 Now create a directory for each virtual host in the directory |
|
64 ''/var/www/vhosts'', and set up appropriate user rights to them: |
|
65 |
|
66 #!ShellExample |
|
67 # cd /var/www/vhosts |
|
68 # mkdir fred-weasley.com |
|
69 # mkdir george-weasley.com |
|
70 # mkdir ron-weasley.com |
|
71 # chown fred:fred fred-weasley.com |
|
72 # chown george:george george-weasley.com |
|
73 # chown ron:ron ron-weasley.com |
|
74 # chmod 750 * |
|
75 |
|
76 # ls -l /var/www/vhosts |
|
77 |
|
78 drwxr-x--- 7 fred fred 4096 Feb 15 20:18 fred-weasley.com |
|
79 drwxr-x--- 6 george george 4096 Feb 15 11:02 george-weasley.com |
|
80 drwxr-x--- 6 ron ron 4096 Feb 15 11:23 ron-weasley.com |
|
81 |
|
82 Now we have created three directories where the three users cannot see each |
|
83 others' files; however, the lighttpd daemon user can see it all. |
|
84 |
|
85 3.3 Create directory structure for each virtual host |
|
86 |
|
87 Now, we want to create the directory struture needed for each virtual host: |
|
88 |
|
89 #!ShellExample |
|
90 # cd /var/www/vhosts/fred-weasley.com |
|
91 # mkdir html |
|
92 # mkdir includes (optional) |
|
93 # mkdir logs |
|
94 # chown fred:fred * |
|
95 # chown lighttpd:fred logs |
|
96 # chmod 750 * |
|
97 |
|
98 # ls -l /var/www/vhosts/fred-weasley.com |
|
99 |
|
100 drwxr-x--- 14 fred fred 4096 Feb 17 11:55 html |
|
101 drwxr-x--- 2 fred fred 4096 Feb 15 12:05 includes |
|
102 drwxr-x--- 2 lighttpd fred 4096 Feb 15 11:11 logs |
|
103 |
|
104 You need to repeat this for each virtual host, replacing the user name |
|
105 'fred' with the appropriate user name. |
|
106 |
|
107 3.4 Create a FastCGI directory for each user |
|
108 |
|
109 Now we have to do all the fun stuff! |
|
110 |
|
111 Now, go to the ''/var/www/fastcgi'' directory where we want to create a |
|
112 directory for each user. (When we're finished, these directories will hold the |
|
113 sockets to the FastCGI server processes): |
|
114 |
|
115 |
|
116 #!ShellExample |
|
117 # cd /var/www/fastcgi |
|
118 # mkdir fred |
|
119 # mkdir george |
|
120 # mkdir ron |
|
121 # chown fred:fred fred |
|
122 # chown george:george george |
|
123 # chown ron:ron ron |
|
124 # chmod 750 * |
|
125 |
|
126 # ls -l /var/www/fastcgi |
|
127 |
|
128 drwxr-x--- 7 fred fred 4096 Feb 15 20:18 fred |
|
129 drwxr-x--- 6 george george 4096 Feb 15 11:02 george |
|
130 drwxr-x--- 6 ron ron 4096 Feb 15 11:23 ron |
|
131 |
|
132 (Note that the lighttpd user can read all directories, while the three users |
|
133 can only access their own directory.) |
|
134 |
|
135 4. Create a FastCGI start-up script for each user |
|
136 |
|
137 Create a directory that will hold all your FastCGI start-up scripts: |
|
138 |
|
139 #!ShellExample |
|
140 # cd /var/www/fastcgi |
|
141 # mkdir startup |
|
142 # chmod 750 startup |
|
143 |
|
144 # ls -l /var/www/fastcgi |
|
145 |
|
146 drwxr-x--- 7 fred fred 4096 Feb 15 20:18 fred |
|
147 drwxr-x--- 6 george george 4096 Feb 15 11:02 george |
|
148 drwxr-x--- 6 ron ron 4096 Feb 15 11:23 ron |
|
149 drwxr-x--- 6 root root 4096 Feb 15 11:23 startup |
|
150 |
|
151 Now, go to the ''/var/www/fastcgi/startup'' directory, create a start-up script |
|
152 for fred (let's call it fred-startup.sh, using your favourite text editor: |
|
153 |
|
154 #!sh |
|
155 #!/bin/sh |
|
156 |
|
157 ## ABSOLUTE path to the spawn-fcgi binary |
|
158 SPAWNFCGI="/usr/bin/spawn-fcgi" |
|
159 |
|
160 ## ABSOLUTE path to the PHP binary |
|
161 FCGIPROGRAM="/usr/bin/php-cgi" |
|
162 |
|
163 ## bind to tcp-port on localhost |
|
164 FCGISOCKET="/var/www/fastcgi/fred/fred.socket" |
|
165 |
|
166 ## uncomment the PHPRC line, if you want to have an extra php.ini for this user |
|
167 ## store your custom php.ini in /var/www/fastcgi/fred/php.ini |
|
168 ## with an custom php.ini you can improve your security |
|
169 ## just set the open_basedir to the users webfolder |
|
170 ## Example: (add this line in you custom php.ini) |
|
171 ## open_basedir = /var/www/vhosts/fred/html |
|
172 ## |
|
173 #PHPRC="/var/www/fastcgi/fred/" |
|
174 |
|
175 ## number of PHP childs to spawn in addition to the default. Minimum of 2. |
|
176 ## Actual childs = PHP_FCGI_CHILDREN + 1 |
|
177 PHP_FCGI_CHILDREN=5 |
|
178 |
|
179 ## number of request server by a single php-process until is will be restarted |
|
180 PHP_FCGI_MAX_REQUESTS=1000 |
|
181 |
|
182 ## IP adresses where PHP should access server connections from |
|
183 FCGI_WEB_SERVER_ADDRS="127.0.0.1" |
|
184 |
|
185 # allowed environment variables sperated by spaces |
|
186 ALLOWED_ENV="PATH USER" |
|
187 |
|
188 ## if this script is run as root switch to the following user |
|
189 USERID=fred |
|
190 GROUPID=fred |
|
191 |
|
192 ################## no config below this line |
|
193 |
|
194 if test x$PHP_FCGI_CHILDREN = x; then |
|
195 PHP_FCGI_CHILDREN=5 |
|
196 fi |
|
197 |
|
198 export PHP_FCGI_MAX_REQUESTS |
|
199 export FCGI_WEB_SERVER_ADDRS |
|
200 export PHPRC |
|
201 |
|
202 ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS PHPRC" |
|
203 |
|
204 # copy the allowed environment variables |
|
205 E= |
|
206 |
|
207 for i in $ALLOWED_ENV; do |
|
208 E="$E $i=$(eval echo "\$$i")" |
|
209 done |
|
210 |
|
211 # clean environment and set up a new one |
|
212 env - $E $SPAWNFCGI -s $FCGISOCKET -f $FCGIPROGRAM -u $USERID -g $GROUPID -C $PHP_FCGI_CHILDREN |
|
213 |
|
214 chmod 770 $FCGISOCKET |
|
215 |
|
216 Please be careful with the paths, USERID and GROUPID. |
|
217 |
|
218 Note that, in this example, the php process runs as the user we created above |
|
219 ('fred'). This means that the php code will have write access to the html and |
|
220 php files. This can be convenient, but might be a security risk. |
|
221 Alternatively, you could set USERID to 'nobody' (or any other user without any |
|
222 specific permissions), to deny write access to the php process. |
|
223 |
|
224 You need to repeat the process and create a startup-script for each user in the |
|
225 ''/var/www/fastcgi/startup'' directory. (Just copy the file and replace |
|
226 FCGISOCKET, USERID and GROUPID with the correct values). |
|
227 |
|
228 Remember to set execute permissions on all your startup-scripts: |
|
229 |
|
230 |
|
231 #!ShellExample |
|
232 # cd /var/www/fastcgi/startup |
|
233 # chmod 750 * |
|
234 |
|
235 5. Check your PHP configuration |
|
236 |
|
237 If you're uncertain about the location of your php.ini, just run the following |
|
238 command: |
|
239 |
|
240 |
|
241 #!ShellExample |
|
242 $ php-cgi -i | grep php.ini |
|
243 Please check, that you have the following line in your php.ini: |
|
244 |
|
245 |
|
246 cgi.fix_pathinfo=1 |
|
247 |
|
248 If you have uncommented the PHPRC line in the shell script under issue 4., be |
|
249 sure that the php.ini has the correct owner an rights. To get things work this |
|
250 must be |
|
251 |
|
252 chmod 644 php.ini |
|
253 chown root:root php.ini |
|
254 |
|
255 6. Execute all FastCGI start-up scripts |
|
256 |
|
257 Now, fire up all your FastCGI server processes: |
|
258 |
|
259 #!ShellExample |
|
260 # /var/www/fastcgi/startup/fred-startup.sh |
|
261 spawn-fcgi.c.170: child spawned successfully: PID: xxxxx |
|
262 # /var/www/fastcgi/startup/george-startup.sh |
|
263 spawn-fcgi.c.170: child spawned successfully: PID: xxxxx |
|
264 # /var/www/fastcgi/startup/ron-startup.sh |
|
265 spawn-fcgi.c.170: child spawned successfully: PID: xxxxx |
|
266 |
|
267 If you get any error messages, please re-check your startup-scripts and the |
|
268 permissions to the ''/var/www/fastcgi'' directory, including all user |
|
269 sub-directories. |
|
270 |
|
271 7. Configure virtual hosts in the lighttpd server |
|
272 |
|
273 Edit ''/etc/lighttpd.conf'' in your favourite text-editor: |
|
274 |
|
275 |
|
276 .....[lots of configuration stuff above]..... |
|
277 |
|
278 $HTTP["host"] =~ "(^|\.)fred-weasley.com$" { |
|
279 server.document-root = "/var/www/vhosts/fred-weasley.com/html" |
|
280 accesslog.filename = "/var/www/vhosts/fred-weasley.com/logs/access_log" |
|
281 fastcgi.server = ( ".php" => |
|
282 ( |
|
283 ( "socket" => "/var/www/fastcgi/fred/fred.socket", |
|
284 "broken-scriptfilename" => "enable" |
|
285 ) |
|
286 ) |
|
287 ) |
|
288 } |
|
289 |
|
290 $HTTP["host"] =~ "(^|\.)george-weasley.com$" { |
|
291 server.document-root = "/var/www/vhosts/george-weasley.com/html" |
|
292 accesslog.filename = "/var/www/vhosts/george-weasley.com/logs/access_log" |
|
293 fastcgi.server = ( ".php" => |
|
294 ( |
|
295 ( "socket" => "/var/www/fastcgi/george/george.socket", |
|
296 "broken-scriptfilename" => "enable" |
|
297 ) |
|
298 ) |
|
299 ) |
|
300 } |
|
301 |
|
302 $HTTP["host"] =~ "(^|\.)ron-weasley.com$" { |
|
303 server.document-root = "/var/www/vhosts/ron-weasley.com/html" |
|
304 accesslog.filename = "/var/www/vhosts/ron-weasley.com/logs/access_log" |
|
305 fastcgi.server = ( ".php" => |
|
306 ( |
|
307 ( "socket" => "/var/www/fastcgi/ron/ron.socket", |
|
308 "broken-scriptfilename" => "enable" |
|
309 ) |
|
310 ) |
|
311 ) |
|
312 } |
|
313 |
|
314 Please note the paths to the FastCGI sockets for each virtual host. |
|
315 |
|
316 '''server.errorlog is NOT working in conditionals, all errors go to the last |
|
317 logfile specified. So just use one global error log.''' |
|
318 |
|
319 8. Restart the lighttpd daemon process |
|
320 |
|
321 Simply run this command: |
|
322 |
|
323 #!ShellExample |
|
324 # /etc/init.d/lighttpd restart |
|
325 If you get any errors, please re-check your ''/etc/lighttpd.conf'' configuration file. |
|
326 |
|
327 9. Hello World! |
|
328 |
|
329 Now, log in as the user fred and create a PHP script file in his virtual host |
|
330 (e.g. ''/var/www/vhosts/fred-weasley.com/html/index.php''): |
|
331 |
|
332 |
|
333 #!php |
|
334 <?php |
|
335 echo "<h1>Hello World!</h1>"; |
|
336 echo "<p>Current User ID is: ". posix_getuid(); |
|
337 echo "<p>Current Group ID is: ". posix_getgid(); |
|
338 ?> |
|
339 Also, make sure to set the file permissions: |
|
340 |
|
341 |
|
342 #!ShellExample |
|
343 # chown fred:fred /var/www/vhosts/fred-weasley.com/html/index.php |
|
344 # chmod 640 /var/www/vhosts/fred-weasley.com/html/index.php |
|
345 |
|
346 # ls -l /var/www/vhosts/fred-weasley.com/html |
|
347 |
|
348 -rw-r----- 1 fred fred 116 Jul 25 2004 index.php |
|
349 |
|
350 Now fire up your web-browser and check the output of your PHP script. (Here: |
|
351 http://www.fred-weasley.com/index.php) |
|
352 |
|
353 If everything went well, you will see an output showing the User ID of the user |
|
354 fred, and the Group ID of the user group fred. (You can see these IDs in the |
|
355 files ''/etc/passwd_ and _/etc/group''). |
|
356 |
|
357 10. Automatically start the FastCGI startup scripts |
|
358 |
|
359 Optionally, you may also create a crontab entry to automatically execute the |
|
360 FastCGI startup scripts when your server boots. |
|
361 |
|
362 Use the following command to edit your crontab: |
|
363 |
|
364 |
|
365 # crontab -e |
|
366 Now add the following line: |
|
367 |
|
368 |
|
369 @reboot for i in /var/www/fastcgi/startup/*.sh; do $i; done |
|
370 And finally type ":x" to save and exit. |
|
371 |
|
372 This crontab entry will execute all .sh files found in the |
|
373 /var/www/fastcgi/startup directory after the server has booted. |
|
374 |
|
375 Congratulations! You now have a working fast server configuration with |
|
376 individual (separate) user rights. |
|
377 |
|
378 Limitations |
|
379 |
|
380 Using this model you are creating a separate pool of fastcgi processes for each |
|
381 user. This means that no memory will be shared between these processes. |
|
382 Therefore, if you use this model for a machine with a large number of users you |
|
383 will need a significant amount of available RAM. Also, if you use any PHP |
|
384 opcode cache such as xcache, apc or eaccelerator, this model means that each |
|
385 user will get their own dedicated cache (which is a good thing from a security |
|
386 perspective, but bad for memory usage). You can tailor the memory used by |
|
387 having different php.ini files that configure the accelerator with differing |
|
388 cache sizes, and by altering the value of PHP_FCGI_CHILDREN in each user's |
|
389 startup.sh script. |
|
390 |
|
391 In FreeBSD (6.2) every user can be in a maximum of 14 groups. This is the upper |
|
392 bound for webhost-fastcgi-instances, as your lighty-user (www) needs access to |
|
393 those sockets. I installed my webhost 1-2 years ago in this way and run in |
|
394 trouble a few weeks ago while adding www to it's 15th group. No error-msg gaves |
|
395 a hint. Go, and google for it. By the way: Is there a solution? ;) - Yes, |
|
396 FreeBSD 8.0 will raise this limitation to 1024. |
|
397 |
|
398 Permissions |
|
399 |
|
400 mod_fastcgi has an option: check-local. When enabled, Lighty uses his user to |
|
401 check if the file exists in document-root. If you want Lighty's user to not |
|
402 have access to the document-root, this option must be disabled. |
|
403 |