SUGGESTION - ssl-load-extra-files - private key name resolution

2020-09-21 Thread Marc Antoine Leclercq
Hi,

I posted this on the discourse haproxy forum and was asked to post it
here for better visibility :

We recently switched to haproxy 2.2.2 and we encountered a problem
with the flexibility of ssl-load-extra-files.

The way we handle certs is as follows:
Public key name is : fqdn.pem
Private key name is : fqdn.key

Which resulted in No Private Key found in
'/etc/pki/tls/certs/fqdn.pem' or /etc/pki/tls/certs/fqdn.pem.key

I think it would be interesting if that directive was a little smarter
in the way it deals with file extensions and also tried to strip the
extension from the filename to see if the .key file exists with the
same name.

Not sure how that would affect performance for HaProxy startup, but
for the moment, we either need to completely revamp the way we deploy
certs, or create a symlink for the key file, to .pem.key in the same
directory if we want to use this feature.
SSL-LOAD-EXTRA-FILES is an excellent feature we’ve been waiting for as
it simplifies our cert deployment, but in its current form It’s not
really usable for us.

Thank you.
-- 

Marc-Antoine Leclercq



Re: Using sockets from Lua

2015-08-26 Thread Marc-Antoine
Great, no more segfault !
Tx a lot ;)

On Tue, 25 Aug 2015 18:28:31 +0200,
Willy Tarreau w...@1wt.eu wrote :

 On Tue, Aug 25, 2015 at 05:27:59PM +0200, Thierry FOURNIER wrote:
  Hello,
  
  Thank you for the bug repport. It is fixed in the current developpment
  version. You must compile from sources or wait for the next dev release.
  
  Actually, the function txn.close() causes a segfault, it will be
  fixed in a few time.
 
 I just merged your temporary fix, Thierry, so the segfault is supposed
 to be gone. CCing Marc-Antoine and Cyril on this. In the mean time, guys,
 please don't add code after txn.close(), as it more or less expects to be
 final. In all your examples it was already fine, but if we manage to enforce
 it to be final, you'll get less surprizes later :-)
 
 Thanks,
 Willy
 


-- 
Marc-Antoine



Re: ocsp

2015-08-18 Thread Marc-Antoine
Hi, i did tests you want. see below for answers.

On Mon, 20 Jul 2015 17:42:03 +0200,
Lukas Tribus luky...@hotmail.com wrote :

  Hi Lukas,
 
  frontend cluster:443
  bind 1.2.3.4:443 ssl strict-sni crt /home/provisionning/0.pem crt 
  /home/provisionning/cluster.d
  default_backend cluster
  capture request header Host len 255
 
 Can you confirm there is no SSL intercepting device in front of the 
 webserver, like
 hardware firewalls/UTM and whatnot?
yes
 
 Could you try with just a single certificate (single crt config pointing to a 
 single certificate file, not a
 directory)?
yes it works fine with crt pointing to a signe certificate file.
 
 Can you make the openssl tests from the server, connecting locally without 
 any intermediate
 devices?
i did and results are the same.

Regards, 
 
 
 
 Thanks,
 
 Lukas
 
 


-- 
Marc-Antoine



Re: segfault in src/buffer.c

2015-08-18 Thread Marc-Antoine
Hi Thierry,

using lua file and cfg file i provided in my two first mails and lastest 
source, you should get segault when doing :

# curl http://127.0.0.1 -H X-debug-me: yes

Regards,

On Tue, 18 Aug 2015 12:33:40 +0200,
Thierry t...@thierry.1s.fr wrote :

 Hi,
 
 How can I reproduce the segfault ?
 
 Thierry
 
 On Mon, 17 Aug 2015 15:00:25 +0200
 Marc-Antoine marc-antoine.b...@ovh.net wrote:
 
  Hi,
  
  Cyril, as you said, if removed txn:close() from the lua script, I don't 
  get segfault anymore.
  
  I noticed that if I removed default_backend line from frontend declaration, 
  segfault does not happen even with txn:close() in lua script :
  
  frontend fe:80
  bind 127.0.0.1:80
  acl debugme req.hdr_cnt(X-debug-me) ge 1
  http-request lua mirror if debugme
  #default_backend be
  
  Regards,
  
  On Sat, 15 Aug 2015 23:56:57 +0200,
  Cyril Bonté cyril.bo...@free.fr wrote :
  
   Hi Marc-Antoine,
   
   Le 12/08/2015 19:01, Marc-Antoine a écrit :
I forgot lua file content :
   
# cat mylua.lua
-- a simple mirror web server
-- it generates a response whose body contains the requests headers
function mirror(txn)
 (...)
 txn:close()
end
   
   This is the call which produce a segfault later, combined with the 
   haproxy configuration. I give more details below.
   
Marc-Antoine marc-antoine.b...@ovh.net wrote :
 (...)
defaults
 modehttp
(...)
frontend fe:80
 bind 127.0.0.1:80
 acl debugme req.hdr_cnt(X-debug-me) ge 1
 http-request lua mirror if debugme
 default_backend be
   
   It looks that currently, mode http doesn't allow a call to txn:close().
   To extend the issue, txn:close() won't work for a proxy in HTTP mode for 
   both :
   http-request lua
   tcp-request content lua
   
   This is due to the stream processing which still execute some request 
   analyzers even if the lua code sends a response and asks to close the 
   transaction.
   
   I haven't looked at the code enough yet, but maybe we should try to find 
   a way to notify haproxy to stop the processing once txn:close() is called.
   
   This also explains some other segfaults reported in the past :
   http://comments.gmane.org/gmane.comp.web.haproxy/21136
   
  
  
  -- 
  Marc-Antoine
  
 


-- 
Marc-Antoine



Re: segfault in src/buffer.c

2015-08-17 Thread Marc-Antoine
Hi,

Cyril, as you said, if removed txn:close() from the lua script, I don't get 
segfault anymore.

I noticed that if I removed default_backend line from frontend declaration, 
segfault does not happen even with txn:close() in lua script :

frontend fe:80
bind 127.0.0.1:80
acl debugme req.hdr_cnt(X-debug-me) ge 1
http-request lua mirror if debugme
#default_backend be

Regards,

On Sat, 15 Aug 2015 23:56:57 +0200,
Cyril Bonté cyril.bo...@free.fr wrote :

 Hi Marc-Antoine,
 
 Le 12/08/2015 19:01, Marc-Antoine a écrit :
  I forgot lua file content :
 
  # cat mylua.lua
  -- a simple mirror web server
  -- it generates a response whose body contains the requests headers
  function mirror(txn)
   (...)
   txn:close()
  end
 
 This is the call which produce a segfault later, combined with the 
 haproxy configuration. I give more details below.
 
  Marc-Antoine marc-antoine.b...@ovh.net wrote :
   (...)
  defaults
   modehttp
  (...)
  frontend fe:80
   bind 127.0.0.1:80
   acl debugme req.hdr_cnt(X-debug-me) ge 1
   http-request lua mirror if debugme
   default_backend be
 
 It looks that currently, mode http doesn't allow a call to txn:close().
 To extend the issue, txn:close() won't work for a proxy in HTTP mode for 
 both :
 http-request lua
 tcp-request content lua
 
 This is due to the stream processing which still execute some request 
 analyzers even if the lua code sends a response and asks to close the 
 transaction.
 
 I haven't looked at the code enough yet, but maybe we should try to find 
 a way to notify haproxy to stop the processing once txn:close() is called.
 
 This also explains some other segfaults reported in the past :
 http://comments.gmane.org/gmane.comp.web.haproxy/21136
 


-- 
Marc-Antoine



ECC certificate

2015-08-12 Thread Marc-Antoine
Hi all,

i'm trying to use an ECC certificate under haproxy without success :

* haproxy -vv
HA-Proxy version 1.5.8 2014/10/31
Copyright 2000-2014 Willy Tarreau w...@1wt.eu

Build options :
  TARGET  = linux2628
  CPU = generic
  CC  = gcc
  CFLAGS  = -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat 
-Werror=format-security -D_FORTIFY_SOURCE=2
  OPTIONS = USE_ZLIB=1 USE_OPENSSL=1 USE_PCRE=1

Default settings :
  maxconn = 2000, bufsize = 16384, maxrewrite = 8192, maxpollevents = 200

Encrypted password support via crypt(3): yes
Built with zlib version : 1.2.7
Compression algorithms supported : identity, deflate, gzip
Built with OpenSSL version : OpenSSL 1.0.1e 11 Feb 2013
Running on OpenSSL version : OpenSSL 1.0.1e 11 Feb 2013
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports prefer-server-ciphers : yes
Built with PCRE version : 8.30 2012-02-04
PCRE library supports JIT : no (USE_PCRE_JIT not set)
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT 
IP_FREEBIND

Available polling systems :
  epoll : pref=300,  test result OK
   poll : pref=200,  test result OK
 select : pref=150,  test result OK
Total: 3 (3 usable), will use epoll.

* conf :

global
ssl-default-bind-ciphers 
kEECDH+aRSA+AES:kRSA+AES:+AES256:!kEDH:!LOW:!EXP:!MD5:!RC4:!aNULL:!eNULL
ssl-default-bind-options no-sslv3

frontend cluster2:443
bind 1.2.3.4:443 ssl strict-sni crt /home/provisionning/0.pem crt 
/home/provisionning/cluster2.d
default_backend cluster2

any idea ?

-- 
Marc-Antoine



Re: ECC certificate

2015-08-12 Thread Marc-Antoine
Hi,

it jus added kEECDH+aECDSA+AES in front on my cipher list and it works fine !

tx

Regards,

On Wed, 12 Aug 2015 11:33:15 +0200,
Robin Geuze rob...@transip.nl wrote :

 ECC certs don't work with your keychain since it only contains RSA based 
 ciphers and not ecdsa based ones.
 
 Baptiste wrote on 8/12/2015 11:29:
  On Wed, Aug 12, 2015 at 11:22 AM, Marc-Antoine
  marc-antoine.b...@ovh.net wrote:
  Hi all,
 
  i'm trying to use an ECC certificate under haproxy without success :
 
  * haproxy -vv
  HA-Proxy version 1.5.8 2014/10/31
  Copyright 2000-2014 Willy Tarreau w...@1wt.eu
 
  Build options :
 TARGET  = linux2628
 CPU = generic
 CC  = gcc
 CFLAGS  = -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat 
  -Werror=format-security -D_FORTIFY_SOURCE=2
 OPTIONS = USE_ZLIB=1 USE_OPENSSL=1 USE_PCRE=1
 
  Default settings :
 maxconn = 2000, bufsize = 16384, maxrewrite = 8192, maxpollevents = 200
 
  Encrypted password support via crypt(3): yes
  Built with zlib version : 1.2.7
  Compression algorithms supported : identity, deflate, gzip
  Built with OpenSSL version : OpenSSL 1.0.1e 11 Feb 2013
  Running on OpenSSL version : OpenSSL 1.0.1e 11 Feb 2013
  OpenSSL library supports TLS extensions : yes
  OpenSSL library supports SNI : yes
  OpenSSL library supports prefer-server-ciphers : yes
  Built with PCRE version : 8.30 2012-02-04
  PCRE library supports JIT : no (USE_PCRE_JIT not set)
  Built with transparent proxy support using: IP_TRANSPARENT 
  IPV6_TRANSPARENT IP_FREEBIND
 
  Available polling systems :
 epoll : pref=300,  test result OK
  poll : pref=200,  test result OK
select : pref=150,  test result OK
  Total: 3 (3 usable), will use epoll.
 
  * conf :
 
  global
   ssl-default-bind-ciphers 
  kEECDH+aRSA+AES:kRSA+AES:+AES256:!kEDH:!LOW:!EXP:!MD5:!RC4:!aNULL:!eNULL
   ssl-default-bind-options no-sslv3
 
  frontend cluster2:443
   bind 1.2.3.4:443 ssl strict-sni crt /home/provisionning/0.pem crt 
  /home/provisionning/cluster2.d
   default_backend cluster2
 
  any idea ?
 
  --
  Marc-Antoine
 
  Hi,
 
  Might be related to your Openssl version :/
 
  Baptiste
 
 
 


-- 
Marc-Antoine



[SPAM] segfault in src/buffer.c

2015-08-12 Thread Marc-Antoine

### HTTP ###

frontend fe:80
bind 127.0.0.1:80
acl debugme req.hdr_cnt(X-debug-me) ge 1
http-request lua mirror if debugme
default_backend be

frontend fe:443
bind 127.0.0.1:443 ssl crt /etc/ssl/private
default_backend be

backend be
server s1 127.0.0.2 
server s2 127.0.0.3
server s3 127.0.0.4

Regards,
-- 
Marc-Antoine



Re: [SPAM] segfault in src/buffer.c

2015-08-12 Thread Marc-Antoine
I forgot lua file content :

# cat mylua.lua 
-- a simple mirror web server
-- it generates a response whose body contains the requests headers
function mirror(txn)
local buffer = 
local response = 
local mydate = txn.sc:http_date(txn.f:date())

buffer = buffer .. You sent the following headers\r\n
buffer = buffer .. ===\r\n
buffer = buffer .. txn.req:dup()
buffer = buffer .. ===\r\n

response = response .. HTTP/1.0 200 OK\r\n
response = response .. Server: haproxy-lua/mirror\r\n
response = response .. Content-Type: text/html\r\n
response = response .. Date:  .. mydate .. \r\n
response = response .. Content-Length:  .. buffer:len() .. \r\n
response = response .. Connection: close\r\n
response = response .. \r\n
response = response .. buffer

txn.res:send(response)
txn:close()
end

On Wed, 12 Aug 2015 18:57:50 +0200,
Marc-Antoine marc-antoine.b...@ovh.net wrote :

 Hi,
 
 i try to test lua in haproxy and i got segfault while doing curl request :
 
 # curl http://127.0.0.1 -H X-debug-me: yes
 curl: (52) Empty reply from server
 
 ---
 
 # gdb ./haproxy
 GNU gdb (GDB) 7.4.1-debian
 Copyright (C) 2012 Free Software Foundation, Inc.
 License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
 This is free software: you are free to change and redistribute it.
 There is NO WARRANTY, to the extent permitted by law.  Type show copying
 and show warranty for details.
 This GDB was configured as x86_64-linux-gnu.
 For bug reporting instructions, please see:
 http://www.gnu.org/software/gdb/bugs/...
 Reading symbols from /root/haproxy/haproxy...done.
 (gdb) run -f /etc/haproxy/haproxy.cfg -db
 Starting program: /root/haproxy/haproxy -f /etc/haproxy/haproxy.cfg -db
 
 Program received signal SIGSEGV, Segmentation fault.
 __memmove_ssse3 () at ../sysdeps/x86_64/multiarch/memcpy-ssse3.S:2976
 2976../sysdeps/x86_64/multiarch/memcpy-ssse3.S: Aucun fichier ou dossier 
 de ce type.
 (gdb) bt 
 #0  __memmove_ssse3 () at ../sysdeps/x86_64/multiarch/memcpy-ssse3.S:2976
 #1  0x004130a9 in buffer_insert_line2 (b=0x7e53b0, pos=0x7e541c 
 \r\n, str=0x782850 , len=20) at src/buffer.c:126
 #2  0x00468c99 in http_header_add_tail2 (msg=0x7cd5a0, 
 hdr_idx=0x7cd540, text=0x782850 , len=20) at src/proto_http.c:507
 #3  0x00472ebb in http_process_request (s=0x7cd1e0, req=0x7cd1f0, 
 an_bit=512) at src/proto_http.c:4596
 #4  0x004b7202 in process_stream (t=0x7d4cb0) at src/stream.c:1741
 #5  0x004196c4 in process_runnable_tasks () at src/task.c:238
 #6  0x0040c148 in run_poll_loop () at src/haproxy.c:1515
 #7  0x0040cca2 in main (argc=4, argv=0x7fffe6f8) at 
 src/haproxy.c:1874
 
 ---
 
 # ./haproxy -vv
 HA-Proxy version 1.6-dev3-03d0e4-59 2015/08/11
 Copyright 2000-2015 Willy Tarreau wi...@haproxy.org
 
 Build options :
   TARGET  = linux2628
   CPU = generic
   CC  = gcc
   CFLAGS  = -O0
   OPTIONS = USE_ZLIB=1 USE_OPENSSL=1 USE_PCRE=1
 
 Default settings :
   maxconn = 2000, bufsize = 16384, maxrewrite = 8192, maxpollevents = 200
 
 Encrypted password support via crypt(3): yes
 Built with zlib version : 1.2.7
 Compression algorithms supported : identity(identity), deflate(deflate), 
 raw-deflate(deflate), gzip(gzip)
 Built with OpenSSL version : OpenSSL 1.0.1e 11 Feb 2013
 Running on OpenSSL version : OpenSSL 1.0.1e 11 Feb 2013
 OpenSSL library supports TLS extensions : yes
 OpenSSL library supports SNI : yes
 OpenSSL library supports prefer-server-ciphers : yes
 Built with PCRE version : 8.30 2012-02-04
 PCRE library supports JIT : no (USE_PCRE_JIT not set)
 Built with Lua version : Lua 5.3.1
 Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT 
 IP_FREEBIND
 
 Available polling systems :
   epoll : pref=300,  test result OK
poll : pref=200,  test result OK
  select : pref=150,  test result OK
 Total: 3 (3 usable), will use epoll.
 
 ---
 
 global
 log /dev/loglocal0
 chroot /var/lib/haproxy
 stats socket /run/haproxy/admin.sock mode 660 level admin
 stats timeout 30s
 user haproxy
 group haproxy
 daemon
 nbproc 1
 
 # Default SSL material locations
 ca-base /etc/ssl/certs
 crt-base /etc/ssl/private
 
 # Default ciphers to use on SSL-enabled listening sockets.
 # For more information, see ciphers(1SSL).
 ssl-default-bind-ciphers 
 kEECDH+aECDSA+AES:kEECDH+aRSA+AES:kRSA+AES:+AES256:RC4-SHA:!kEDH:!LOW:!EXP:!MD5:!aNULL:!eNULL
 ssl-default-bind-options no-sslv3
 
 lua-load /root/haproxy/mylua.lua
 
 defaults
 log global
 modehttp
 option  httplog
 option log-health-checks
 option log-separate-errors

Re: ocsp

2015-07-22 Thread Marc-Antoine
Hi,

On Mon, 20 Jul 2015 11:50:50 +0200,
Marc-Antoine marc-antoine.b...@ovh.net wrote :

 Hi Lukas,
 
 frontend cluster:443
 bind 1.2.3.4:443 ssl strict-sni crt /home/provisionning/0.pem crt 
 /home/provisionning/cluster.d
 default_backend cluster
 capture request header Host len 255

using this conf i made some tests. here is /home/provisionning content case and 
result :

---

1)

./0.pem.ocsp
./0.pem
./0.pem.issuer
./cluster.d/8640.pem.ocsp
./cluster.d/8640.pem.issuer
./cluster.d/8485.pem.ocsp
./cluster.d/8485.pem.issuer
./cluster.d/8485.pem
./cluster.d/8640.pem

= ocsp stapling is working for all certs

2)

./0.pem.ocsp
./0.pem
./0.pem.issuer
./cluster.d/8485.pem.ocsp
./cluster.d/8485.pem.issuer
./cluster.d/8485.pem
./cluster.d/8640.pem

= ocsp stapling is working for 0 and 8485 certs and broken for 8640 cert

3)

./0.pem.ocsp
./0.pem
./0.pem.issuer
./cluster.d/8640.pem.ocsp
./cluster.d/8640.pem.issuer
./cluster.d/8485.pem
./cluster.d/8640.pem

= ocsp stapling is working 0 and 8640 certs and broken for 8485 cert

4)

./0.pem
./cluster.d/8640.pem.ocsp
./cluster.d/8640.pem.issuer
./cluster.d/8485.pem.ocsp
./cluster.d/8485.pem.issuer
./cluster.d/8485.pem
./cluster.d/8640.pem

= ocsp stapling is broken for all certs

---

is that a normal behavior ? i think ocsp stapling should work for 8485 and 8640 
certs in case 4.

Regards,

 
 ---
 
 HA-Proxy version 1.5.8 2014/10/31
 Copyright 2000-2014 Willy Tarreau w...@1wt.eu
 
 Build options :
   TARGET  = linux2628
   CPU = generic
   CC  = gcc
   CFLAGS  = -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat 
 -Werror=format-security -D_FORTIFY_SOURCE=2
   OPTIONS = USE_ZLIB=1 USE_OPENSSL=1 USE_PCRE=1
 
 Default settings :
   maxconn = 2000, bufsize = 16384, maxrewrite = 8192, maxpollevents = 200
 
 Encrypted password support via crypt(3): yes
 Built with zlib version : 1.2.7
 Compression algorithms supported : identity, deflate, gzip
 Built with OpenSSL version : OpenSSL 1.0.1e 11 Feb 2013
 Running on OpenSSL version : OpenSSL 1.0.1e 11 Feb 2013
 OpenSSL library supports TLS extensions : yes
 OpenSSL library supports SNI : yes
 OpenSSL library supports prefer-server-ciphers : yes
 Built with PCRE version : 8.30 2012-02-04
 PCRE library supports JIT : no (USE_PCRE_JIT not set)
 Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT 
 IP_FREEBIND
 
 Available polling systems :
   epoll : pref=300,  test result OK
poll : pref=200,  test result OK
  select : pref=150,  test result OK
 Total: 3 (3 usable), will use epoll.
 
 ---
 
 If ocsp file is too old or empty for example, i got warning.
 
 Regards,
 
 On Fri, 17 Jul 2015 21:50:34 +0200,
 Lukas Tribus luky...@hotmail.com wrote :
 
  Hi Marc,
  
  
  
   Hi all,
  
   I have some problem making ocsp stapling working. here is what i did :
  
   I have 8150.pem with chain, cert and key in it.
  
   I have 8150.pem.ocsp that seems ok :
  
   # openssl ocsp -respin 8150.pem.ocsp -text -CAfile alphassl256.chain
   OCSP Response Data:
   OCSP Response Status: successful (0x0)
   Response Type: Basic OCSP Response
   Version: 1 (0x0)
   Responder Id: 9F10D9EDA5260B71A677124526751E17DC85A62F
   Produced At: Jul 9 09:47:04 2015 GMT
   Responses:
   Certificate ID:
   Hash Algorithm: sha1
   Issuer Name Hash: 84D56BF8098BD307B766D8E1EBAD6596AA6B6761
   Issuer Key Hash: F5CDD53C0850F96A4F3AB797DA5683E669D268F7
   Serial Number: 11216784E7CA1813F3AD922B60EAF6428EE0
   Cert Status: good
   This Update: Jul 9 09:47:04 2015 GMT
   Next Update: Jul 9 21:47:04 2015 GMT
  
   No error/warn at haproxy launching but not sure haproxy is loading .ocsp 
   file because no notice in log.
  
   But nothing in tlsextdebug :
  
   echo Q | openssl s_client -connect www.beluc.fr:443 -servername 
   www.beluc.fr -tlsextdebug -status -CApath /etc/ssl/certs
   [...]
   OCSP response: no response sent
   [...]
  
   Do you see smth wrong ? What can i do in order to debug?
  
  Can you provide the output of haproxy -vv please and a
  config snippet (the frontend ssl configuration)?
  
  Do you see a warning if 8150.pem.ocsp contains garbage when you restart
  haproxy?
  
  
  
  Regards,
  
  Lukas
  
  

 
 


-- 
Marc-Antoine



Re: ocsp

2015-07-21 Thread Marc-Antoine
Hi Lukas,

I used only one pem file per frontend instead of pem directory :

frontend cluster1:443
bind 1.2.3.4:443 ssl crt /home/provisionning/cluster1.d/8640.pem
default_backend cluster1

Regards,

On Mon, 20 Jul 2015 20:18:10 +0200,
Lukas Tribus luky...@hotmail.com wrote :

  Hi Lukas,
 
  I made a mistake in my previous email : it works locally AND remotely !
 
 What fixed the problem? This may be useful for others as well.
 
 
 Lukas
 
 

-- 
Marc-Antoine



Re: ocsp

2015-07-20 Thread Marc-Antoine
Hi Lukas,

I made a mistake in my previous email : it works locally AND remotely !

Regards,

On Mon, 20 Jul 2015 19:04:24 +0200,
Lukas Tribus luky...@hotmail.com wrote :

 Hi Marc,
 
 
  Hi Lukas,
 
  great intuition :)
 
  ---
 
  CONNECTED(0003)
  TLS server extension server name (id=0), len=0
  TLS server extension renegotiation info (id=65281), len=1
  0001 - SPACES/NULS
  TLS server extension EC point formats (id=11), len=4
   - 03 00 01 02 
  TLS server extension session ticket (id=35), len=0
  TLS server extension status request (id=5), len=0
  TLS server extension heartbeat (id=15), len=1
   - 01 .
  depth=2 C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
  verify return:1
  depth=1 C = BE, O = GlobalSign nv-sa, CN = AlphaSSL CA - SHA256 - G2
  verify return:1
  depth=0 OU = Domain Control Validated, CN = *.makeprestashop.com
  verify return:1
  OCSP response:
  ==
  OCSP Response Data:
  OCSP Response Status: successful (0x0)
  Response Type: Basic OCSP Response
  Version: 1 (0x0)
  Responder Id: 9F10D9EDA5260B71A677124526751E17DC85A62F
  Produced At: Jul 20 16:42:53 2015 GMT
  Responses:
  Certificate ID:
  Hash Algorithm: sha1
  Issuer Name Hash: 84D56BF8098BD307B766D8E1EBAD6596AA6B6761
  Issuer Key Hash: F5CDD53C0850F96A4F3AB797DA5683E669D268F7
  Serial Number: 11210839AC1CC2D1DC09BA07A33700E3E681
  Cert Status: good
  This Update: Jul 20 16:42:53 2015 GMT
  Next Update: Jul 21 04:42:53 2015 GMT
 
  [...]
 
  ---
 
  It works locally or remotely !
 
 Not sure I understand. Does that mean it works locally, but not remotely?
 
 
 
 Regards,
 
 Lukas
 
 
 

-- 
Marc-Antoine



Re: ocsp

2015-07-15 Thread Marc-Antoine
Hi,

nobody knows plz ?

On Thu, 9 Jul 2015 13:06:59 +0200,
Marc-Antoine marc-antoine.b...@ovh.net wrote :

 Hi all,
 
 I have some problem making ocsp stapling working. here is what i did :
 
 I have 8150.pem with chain, cert and key in it.
 
 I have 8150.pem.ocsp that seems ok :
 
 # openssl ocsp -respin 8150.pem.ocsp -text -CAfile alphassl256.chain 
 OCSP Response Data:
 OCSP Response Status: successful (0x0)
 Response Type: Basic OCSP Response
 Version: 1 (0x0)
 Responder Id: 9F10D9EDA5260B71A677124526751E17DC85A62F
 Produced At: Jul  9 09:47:04 2015 GMT
 Responses:
 Certificate ID:
   Hash Algorithm: sha1
   Issuer Name Hash: 84D56BF8098BD307B766D8E1EBAD6596AA6B6761
   Issuer Key Hash: F5CDD53C0850F96A4F3AB797DA5683E669D268F7
   Serial Number: 11216784E7CA1813F3AD922B60EAF6428EE0
 Cert Status: good
 This Update: Jul  9 09:47:04 2015 GMT
 Next Update: Jul  9 21:47:04 2015 GMT
 
 No error/warn at haproxy launching but not sure haproxy is loading .ocsp file 
 because no notice in log.
 
 But nothing in tlsextdebug :
 
 echo Q | openssl s_client -connect www.beluc.fr:443 -servername www.beluc.fr  
 -tlsextdebug  -status -CApath /etc/ssl/certs
 [...]
 OCSP response: no response sent
 [...]
 
 Do you see smth wrong ? What can i do in order to debug ?
 
 Regards,
 


-- 
Marc-Antoine



ocsp

2015-07-09 Thread Marc-Antoine
Hi all,

I have some problem making ocsp stapling working. here is what i did :

I have 8150.pem with chain, cert and key in it.

I have 8150.pem.ocsp that seems ok :

# openssl ocsp -respin 8150.pem.ocsp -text -CAfile alphassl256.chain 
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: 9F10D9EDA5260B71A677124526751E17DC85A62F
Produced At: Jul  9 09:47:04 2015 GMT
Responses:
Certificate ID:
  Hash Algorithm: sha1
  Issuer Name Hash: 84D56BF8098BD307B766D8E1EBAD6596AA6B6761
  Issuer Key Hash: F5CDD53C0850F96A4F3AB797DA5683E669D268F7
  Serial Number: 11216784E7CA1813F3AD922B60EAF6428EE0
Cert Status: good
This Update: Jul  9 09:47:04 2015 GMT
Next Update: Jul  9 21:47:04 2015 GMT

No error/warn at haproxy launching but not sure haproxy is loading .ocsp file 
because no notice in log.

But nothing in tlsextdebug :

echo Q | openssl s_client -connect www.beluc.fr:443 -servername www.beluc.fr  
-tlsextdebug  -status -CApath /etc/ssl/certs
[...]
OCSP response: no response sent
[...]

Do you see smth wrong ? What can i do in order to debug ?

Regards,

-- 
Marc-Antoine



Re: [ANNOUNCE] haproxy-1.5.14

2015-07-03 Thread Marc-Antoine
Hi, just to let you know changelog is missing 1.5.14 infos ;)

great job by the way !

On Fri, 3 Jul 2015 17:55:56 +0200,
Willy Tarreau w...@1wt.eu wrote :

 Changelog: http://www.haproxy.org/download/1.5/src/CHANGELOG

-- 
Marc-Antoine



Re: Which signal causes HAProxy to reload its config

2015-03-25 Thread Marc-Antoine Perennou
On 25 March 2015 at 12:25, jeff saremi jeffsar...@hotmail.com wrote:
 I have to do manually what -sf is supposed to be doing since it's either 
 not working or not supported and removed.
 I know what that does is send a signal to the pid stored by the haproxy 
 process. I'd like to do that myself.
 Just need to know the signal name.
 thanks
 jeff

Haproxy doesn't reload its config.
-sf is there so that the new haproxy you're spawning tells the old one
to stop accepting new connections and exit once the current one are
closed.
You do not send a signal to the running haproxy process (well, you do,
but not only), you *replace* it.

What you may be looking for, though, is haproxy-systemd-wrapper, which
does all this automatically when it receives SIGUSR2 or SIGHUP.

Regards,
Marc-Antoine



Re: [PATCH] Also accept SIGHUP/SIGTERM in systemd-wrapper

2014-09-11 Thread Marc-Antoine Perennou
On 11 September 2014 07:44, Willy Tarreau w...@1wt.eu wrote:
 On Wed, Sep 10, 2014 at 10:38:55PM -0700, Matt Robenolt wrote:
 Awesome, thanks. :)

 Is it possible to also get this applied into the 1.5 branch since this is 
 low risk and doesn???t break any backwards compatibility and whatnot?

 I've just backported it as well. 1.5 was still missing Conrad Hoffman's
 improved signal handling, but now both patches have been merged.

 Willy



Iirc, the reason why I did not use SIGHUP for the reload (which I'd
have preferred too) is that haproxy itself uses SIGHUP, and if I used
it in the wrapper, it became a noop for haproxy.
Maybe I did something wrong and with the actual state of it it works
fine now, but did you check that haproxy still handles it properly?



Re: [PATCH 0/3] systemd wrapper improvements

2014-04-17 Thread Marc-Antoine Perennou
Hi,

On Thursday, April 17, 2014, Apollon Oikonomopoulos apoi...@debian.org
wrote:

 Hi,

 The following patches improve the systemd wrapper in a couple of ways:

  - The systemd wrapper itself is now re-executed on SIGUSR2, allowing a new
version of both HAProxy and the wrapper to be gracefully loaded.
  - We use standard error for message logging, which seems to get more
 reliably
to systemd's journal than stdout.
  - We also use systemd's support for prefixing messages with the log level
 to
differentiate between message severity.
  - Finally, we propagate the exit status of HAProxy to systemd, instead of
always returning success.

 Regards,
 Apollon

 Apollon Oikonomopoulos (3):
   MINOR: systemd wrapper: re-execute on SIGUSR2
   MINOR: systemd wrapper: improve logging
   MINOR: systemd wrapper: propagate exit status

  src/haproxy-systemd-wrapper.c | 69
 ++-
  1 file changed, 49 insertions(+), 20 deletions(-)

 --
 1.9.1




Looks good to me.
Any comments, Will?

Regards,

Marc-Antoine


Re: haproxy-systemd-wrapper spawning multiple processes

2014-02-15 Thread Marc-Antoine Perennou
Hi,

On 16 February 2014 01:51, Ryan O'Hara roh...@redhat.com wrote:

 I started tinkering with haproxy-systemd-wrapper recently and noticed
 that I get two haproxy processes when I start:

 # systemctl start haproxy
 # systemctl status haproxy
 haproxy.service - HAProxy Load Balancer
Loaded: loaded (/usr/lib/systemd/system/haproxy.service; disabled)
Active: active (running) since Sat 2014-02-15 10:39:20 CST; 1s ago
  Main PID: 10065 (haproxy-systemd)
CGroup: /system.slice/haproxy.service
├─10065 /usr/sbin/haproxy-systemd-wrapper -f
/etc/haproxy/haproxy.cfg -p /run/haproxy
├─10066 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p
/run/haproxy.pid -Ds
└─10067 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p
/run/haproxy.pid -Ds

 That doesn't seem right. A quick look the haproxy processes shows an
 interesting parent/child relationship:

 # ps -C haproxy -o pid,ppid
   PID  PPID
 10066 10065
 10067 10066

 Can someone explain what is going on here? I'm using 1.5-dev22 and the
 systemd service file from the source.


Here is how haproxy works (correct me if I'm wrong, it's not all that
fresh in my mind):
- the main haproxy process is started
- it forks as many child processes as asked in its configuration file
- it goes away letting only the worker child processes

First thing I did was to make it wait for the worker child processes
instead of leaving, that's what -Ds is for. This is in order to avoid
the double fork which would happen because of what I'll describe just
below.

Here is how haproxy reloads its configuration:
- A new haproxy is spawned with the pids of the old workers
- The new haproxy tells the old workers not to listen anymore, and to
exit when they have finished dealing with their current requests
- The new haproxy spawns its own workers and starts listening
- The old haproxy quits eventually when it has dealt with all pending requests

systemd doesn't like this behavious at all as the main process
completely goes away, replaced by a brand new one, just for a
*reload*.

The easiest way to get it working without having to rework the core
behaviour of haproxy was to put a wrapper around it, which spawns
haproxy, listens to a signal which systemd emits on reload, and which
spawns a new haproxy when this signal is received. This way, the main
process never changes ans systemd can reload gracefully.

This is why you get

haproxy-systemd-wrapper - main haproxy process - haproxy worker.

haproxy-systemd-wrapper waits for the main haproxy process to exit to
avoir zombies. The main haproxy process exits when all its workers are
done.

 Thanks.
 Ryan


Hope that helps and sounds right.

Marc-Antoine



Re: haproxy-systemd-wrapper spawning multiple processes

2014-02-15 Thread Marc-Antoine Perennou
On Sat, 2014-02-15 at 20:04 -0600, Ryan O'Hara wrote:
 On Sun, Feb 16, 2014 at 10:08:31AM +0900, Marc-Antoine Perennou wrote:
 
  This is why you get
  
  haproxy-systemd-wrapper - main haproxy process - haproxy worker.
  
  haproxy-systemd-wrapper waits for the main haproxy process to exit to
  avoir zombies. The main haproxy process exits when all its workers are
  done.
 
 It has been while since I dealt with this, but can't you double fork
 to avoid zombies? Is it a double fork that causes problems for systemd?
 

Double forking would work fine, but the wrapper wouldn't be linked to
the worker processes and thus couldn't check whether there has been a
problem or not.
Without the double fork, if there is a problem, the wrapper will exit
and you'll be able to notice it.
With the double fork, we would end up with some kind of endless loop
instead of a waiting loop, and it would never exit.

   Thanks.
   Ryan
  
  
  Hope that helps and sounds right.
  
  Marc-Antoine
 
 It does help. Thank you.
 
 Ryan
 

Regards

Marc-Antoine






Re: Three patches to the haproxy-systemd-wrapper

2013-11-23 Thread Marc-Antoine Perennou
Hello,

On Saturday, November 23, 2013, Willy Tarreau wrote:

 Hello Kristoffer,

 On Fri, Nov 22, 2013 at 11:21:21AM +0100, Kristoffer Grönlund wrote:
  Hello,
 
  I have packaged haproxy 1.4.24 for openSUSE 13.1 [1], which uses systemd
  as the init system. At first I tried using a service script originally
  written for Fedora, but this script didn't handle configuration file
  reload in a good way. I then found the haproxy-systemd-wrapper
  committed upstream, which looked like a more viable approach. However,
  it didn't work for openSUSE mainly because SBINDIR didn't point to the
  correct directory.
 
  There was also an issue with the wrapper not cleaning up when killed by
  systemd, leaving zombie processes hanging.
 
  The attached patches should address both of these issues in a way that
  should work on any systemd-platform. I also added some logging to the
  systemd-wrapper so that it's easier to figure out what it does.
 
  The patched wrapper seems to work well for me, but any
  comments/suggestions are welcome. :)
 
  In case the patches get stripped, they are also available from my
  github account [2]. They are applied to a copy of 1.4.24 there, but
  should apply cleanly to the development tree.

 Great, thank you! I'll wait for Marc-Antoine to do a quick review since
 he seems to be the only one here having had his fingers dirty with
 systemd, then I have no problem merging them.

 Thanks!
 Willy


I don't have access to a computer to actually test those, but:
- the first one looks nice, never felt really confident hard coding SBINDIR
and the solution makes sense
- nice catch for the second one, didn't think of the sigint when writing
it, lgtm
- third one is trivial enough not to harm anyone

+1 for me

Thanks!

Marc-Antoine


[PATCH] BUG/MEDIUM: systemd-wrapper: don't leak zombie processes

2013-04-02 Thread Marc-Antoine Perennou
Formerly, if A was replaced by B, and then B by C before
A finished exiting, we didn't wait for B to finish so it
ended up as a zombie process.
Fix this by waiting randomly every child we spawn.

Signed-off-by: Marc-Antoine Perennou marc-anto...@perennou.com
---
 src/haproxy-systemd-wrapper.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c
index 5968015..8499b35 100644
--- a/src/haproxy-systemd-wrapper.c
+++ b/src/haproxy-systemd-wrapper.c
@@ -19,12 +19,11 @@
 #include unistd.h
 #include sys/wait.h
 
-static pid_t pid = 0;
 static char *pid_file = /run/haproxy.pid;
 static int main_argc;
 static char **main_argv;
 
-static pid_t spawn_haproxy(char **pid_strv, int nb_pid)
+static void spawn_haproxy(char **pid_strv, int nb_pid)
 {
pid_t pid = fork();
if (!pid) {
@@ -45,7 +44,6 @@ static pid_t spawn_haproxy(char **pid_strv, int nb_pid)
execv(argv[0], argv);
exit(0);
}
-   return pid;
 }
 
 static int read_pids(char ***pid_strv)
@@ -77,7 +75,7 @@ static void signal_handler(int signum __attribute__((unused)))
char **pid_strv = NULL;
int nb_pid = read_pids(pid_strv);
 
-   pid = spawn_haproxy(pid_strv, nb_pid);
+   spawn_haproxy(pid_strv, nb_pid);
 
for (i = 0; i  nb_pid; ++i)
free(pid_strv[i]);
@@ -107,8 +105,8 @@ int main(int argc, char **argv)
 
signal(SIGUSR2, signal_handler);
 
-   pid = spawn_haproxy(NULL, 0);
-   while (-1 != waitpid(pid, NULL, 0) || errno == EINTR);
+   spawn_haproxy(NULL, 0);
+   while (-1 != wait(NULL) || errno == EINTR);
 
return EXIT_SUCCESS;
 }
-- 
1.8.2




Re: [PATCH v2] BUG/MEDIUM: systemd-wrapper: don't leak zombie processes

2013-04-01 Thread Marc-Antoine Perennou
Hi,

After checking out the man page of waitpid, wait would indeed be sufficient
here.
I didn't actually know about waitpid(-1)

I'll resubmit an updated patch tomorrow!

Thanks



On 1 April 2013 23:32, Willy Tarreau w...@1wt.eu wrote:

 Hi Marc-Antoine,

 On Thu, Mar 14, 2013 at 02:50:56PM +0100, Marc-Antoine Perennou wrote:
  Formerly, if A was replaced by B, and then B by C before
  A finished exiting, we didn't wait for B to finish so it
  ended up as a zombie process.
  Fix this by queuing all process we spawn for waitpid.

 I'm a bit puzzled, why is it necessary to keep a queue of all spawned
 processes ? The system already has one, so we should simply do a wait()
 or waitpid(-1).

 Am I missing something ?

 Willy




[PATCH v2] BUG/MEDIUM: systemd-wrapper: don't leak zombie processes

2013-03-14 Thread Marc-Antoine Perennou
Formerly, if A was replaced by B, and then B by C before
A finished exiting, we didn't wait for B to finish so it
ended up as a zombie process.
Fix this by queuing all process we spawn for waitpid.

Signed-off-by: Marc-Antoine Perennou marc-anto...@perennou.com
---
 src/haproxy-systemd-wrapper.c | 45 +--
 1 file changed, 43 insertions(+), 2 deletions(-)

diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c
index 5968015..a3af528 100644
--- a/src/haproxy-systemd-wrapper.c
+++ b/src/haproxy-systemd-wrapper.c
@@ -24,6 +24,44 @@ static char *pid_file = /run/haproxy.pid;
 static int main_argc;
 static char **main_argv;
 
+static struct {
+   pid_t *queue;
+   int count;
+   int size;
+   int index;
+   int rindex;
+} pids = {
+   .queue = NULL,
+   .count = 0,
+   .size = 8,
+   .index = 0,
+   .rindex = 0
+};
+
+static void pids_push(pid_t pid)
+{
+   if (pids.size == pids.count) {
+   // Double the capacity, write in the new half, rewind reading 
head
+   pids.index = pids.size;
+   pids.rindex = 0;
+   pids.size *= 2;
+   pids.queue = realloc(pids.queue, pids.size * sizeof(int));
+   }
+   pids.queue[pids.index++ % pids.size] = pid;
+   pids.count++;
+}
+
+static bool pids_pop(void)
+{
+   if (pids.count == 0)
+   pid = 0;
+   else {
+   pids.count--;
+   pid = pids.queue[pids.rindex++ % pids.size];
+   }
+   return pid != 0;
+}
+
 static pid_t spawn_haproxy(char **pid_strv, int nb_pid)
 {
pid_t pid = fork();
@@ -77,7 +115,7 @@ static void signal_handler(int signum 
__attribute__((unused)))
char **pid_strv = NULL;
int nb_pid = read_pids(pid_strv);
 
-   pid = spawn_haproxy(pid_strv, nb_pid);
+   pids_push(spawn_haproxy(pid_strv, nb_pid));
 
for (i = 0; i  nb_pid; ++i)
free(pid_strv[i]);
@@ -107,8 +145,11 @@ int main(int argc, char **argv)
 
signal(SIGUSR2, signal_handler);
 
+   pids.queue = malloc(pids.size * sizeof(int));
pid = spawn_haproxy(NULL, 0);
-   while (-1 != waitpid(pid, NULL, 0) || errno == EINTR);
+   while ((-1 != waitpid(pid, NULL, 0)  pids_pop()) || errno == EINTR);
+
+   free(pids.queue);
 
return EXIT_SUCCESS;
 }
-- 
1.8.1.5




[PATCH] MEDIUM: systemd-wrapper: don't leak zombie processes

2013-02-25 Thread Marc-Antoine Perennou
Formerly, if A was replaced by B, and then B by C before
A finished exiting, we didn't wait for B to finish so it
ended up as a zombie process.
Fix this by queuing all process we spawn for waitpid.

Signed-off-by: Marc-Antoine Perennou marc-anto...@perennou.com
---
 src/haproxy-systemd-wrapper.c | 45 +--
 1 file changed, 43 insertions(+), 2 deletions(-)

diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c
index 57e8d7d..3c70271 100644
--- a/src/haproxy-systemd-wrapper.c
+++ b/src/haproxy-systemd-wrapper.c
@@ -24,6 +24,44 @@ static char *pid_file = /run/haproxy.pid;
 static int main_argc;
 static char **main_argv;
 
+static struct {
+   pid_t *queue;
+   int count;
+   int size;
+   int index;
+   int rindex;
+} pids = {
+   .queue = NULL,
+   .count = 0,
+   .size = 8,
+   .index = 0,
+   .rindex = 0
+};
+
+static void pids_push(pid_t pid)
+{
+   if (pids.size == pids.count) {
+   // Double the capacity, write in the new half, rewind reading 
head
+   pids.index = pids.size;
+   pids.rindex = 0;
+   pids.size *= 2;
+   pids.queue = realloc(pids.queue, pids.size * sizeof(int));
+   }
+   pids.queue[pids.index++ % pids.size] = pid;
+   pids.count++;
+}
+
+static bool pids_pop(void)
+{
+   if (pids.count == 0)
+   pid = 0;
+   else {
+   pids.count--;
+   pid = pids.queue[pids.rindex++ % pids.size];
+   }
+   return pid != 0;
+}
+
 static pid_t spawn_haproxy(char **pid_strv, int nb_pid)
 {
pid_t pid = fork();
@@ -76,7 +114,7 @@ static void signal_handler(int signum 
__attribute__((unused)))
char **pid_strv = NULL;
int nb_pid = read_pids(pid_strv);
 
-   pid = spawn_haproxy(pid_strv, nb_pid);
+   pids_push(spawn_haproxy(pid_strv, nb_pid));
 
for (i = 0; i  nb_pid; ++i)
free(pid_strv[i]);
@@ -106,8 +144,11 @@ int main(int argc, char **argv)
 
signal(SIGUSR2, signal_handler);
 
+   pids.queue = malloc(pids.size * sizeof(int));
pid = spawn_haproxy(NULL, 0);
-   while (-1 != waitpid(pid, NULL, 0) || errno == EINTR);
+   while ((-1 != waitpid(pid, NULL, 0) || errno == EINTR)  pids_pop());
+
+   free(pids.queue);
 
return EXIT_SUCCESS;
 }
-- 
1.8.1.3




Re: [[V2] 3/3] MEDIUM: add systemd service

2013-02-13 Thread Marc-Antoine Perennou
Hi,

On 13 February 2013 08:11, Willy Tarreau w...@1wt.eu wrote:

 Hi Marc-Antoine,

 On Tue, Feb 12, 2013 at 10:53:54AM +0100, Marc-Antoine Perennou wrote:
  +systemd/haproxy.service: contrib/systemd/haproxy.service.in
  + mkdir -p systemd
  + sed -e 's:@SBINDIR@:'$(strip $(SBINDIR))':' $  $@
  +

 I'm a bit worried with this one, because it will create a new systemd
 directory in everyone's sources, which is even not cleaned afterwards.
 I'd rather keep the usual behaviour we have with whatever lies in the
 contrib subdir, which consists in considering them as add-ons and
 leaving them completely in that directory. In my opinion you should
 create a simple makefile there so that the packager may just run
 make -C contrib/systemd to build it and have the result in the
 contrib/systemd directory.


Sure, will do


  diff --git a/contrib/systemd/haproxy.service.in b/contrib/systemd/
 haproxy.service.in
  new file mode 100644
  index 000..f925651
  --- /dev/null
  +++ b/contrib/systemd/haproxy.service.in
  @@ -0,0 +1,11 @@
  +[Unit]
  +Description=HAProxy Load Balancer
  +After=network.target
  +
  +[Service]
  +ExecStart=@SBINDIR@/haproxy-systemd-wrapper -f
 /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
  +ExecReload=/usr/bin/kill -USR2 $MAINPID

 You should be careful here. On my distro, kill is in /bin, not in
 /usr/bin. I don't know if it's standard to have it in /usr/bin on
 distros which involve systemd, but at first glance it might not be
 very much portable. Oh and BTW my distro seems to be right about it,
 so please double-check :

http://refspecs.linuxfoundation.org/FHS_2.3/fhs-2.3.html

 Regards,
 Willy


My bad, /bin is actually a symlink to /usr/bin on my system, but you're
right it should be /bin, not /usr/bin, will fix it


[[V3] 3/3] MEDIUM: add systemd service

2013-02-13 Thread Marc-Antoine Perennou
Signed-off-by: Marc-Antoine Perennou marc-anto...@perennou.com
---
 .gitignore |  1 +
 contrib/systemd/Makefile   |  8 
 contrib/systemd/haproxy.service.in | 11 +++
 3 files changed, 20 insertions(+)
 create mode 100644 contrib/systemd/Makefile
 create mode 100644 contrib/systemd/haproxy.service.in

diff --git a/.gitignore b/.gitignore
index 5e6f556..ec1545a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,4 @@ haproxy-*
 make-*
 dlmalloc.c
 00*.patch
+*.service
diff --git a/contrib/systemd/Makefile b/contrib/systemd/Makefile
new file mode 100644
index 000..e542c23
--- /dev/null
+++ b/contrib/systemd/Makefile
@@ -0,0 +1,8 @@
+PREFIX = /usr/local
+SBINDIR = $(PREFIX)/sbin
+
+haproxy.service: haproxy.service.in
+   sed -e 's:@SBINDIR@:'$(strip $(SBINDIR))':' $  $@
+
+clean:
+   rm -f haproxy.service
diff --git a/contrib/systemd/haproxy.service.in 
b/contrib/systemd/haproxy.service.in
new file mode 100644
index 000..1a3d2c0
--- /dev/null
+++ b/contrib/systemd/haproxy.service.in
@@ -0,0 +1,11 @@
+[Unit]
+Description=HAProxy Load Balancer
+After=network.target
+
+[Service]
+ExecStart=@SBINDIR@/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p 
/run/haproxy.pid
+ExecReload=/bin/kill -USR2 $MAINPID
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
-- 
1.8.1.2




[[V2] 1/3] MEDIUM: New cli option -Ds for systemd compatibility

2013-02-12 Thread Marc-Antoine Perennou
This patch adds a new option -Ds which is exactly like -D, but instead of
forking n times to get n jobs running and then exiting, prefers to wait for all 
the
children it just created. With this done, haproxy becomes more 
systemd-compliant,
without changing anything for other systems.

Signed-off-by: Marc-Antoine Perennou marc-anto...@perennou.com
---
 doc/haproxy-en.txt |  1 +
 doc/haproxy-fr.txt |  1 +
 doc/haproxy.1  |  4 
 include/types/global.h |  1 +
 src/haproxy.c  | 35 +++
 5 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/doc/haproxy-en.txt b/doc/haproxy-en.txt
index 3d2a2be..4c673d3 100644
--- a/doc/haproxy-en.txt
+++ b/doc/haproxy-en.txt
@@ -51,6 +51,7 @@ There are only a few command line options :
= 'maxconn' in 'listen' or 'default' sections
 -d starts in foregreound with debugging mode enabled
 -D starts in daemon mode
+-Ds starts in systemd daemon mode
 -q disable messages on output
 -V displays messages on output even when -q or 'quiet' are specified.
 -c only checks config file and exits with code 0 if no error was found, or
diff --git a/doc/haproxy-fr.txt b/doc/haproxy-fr.txt
index 87bb972..0e36724 100644
--- a/doc/haproxy-fr.txt
+++ b/doc/haproxy-fr.txt
@@ -53,6 +53,7 @@ Les options de lancement sont peu nombreuses :
= 'maxconn' dans les sections 'listen' ou 'default'
 -d active le mode debug
 -D passe en daemon
+-Ds passe en daemon systemd
 -q d�sactive l'affichage de messages sur la sortie standard.
 -V affiche les messages sur la sortie standard, m�me si -q ou 'quiet' sont
sp�cifi�s.
diff --git a/doc/haproxy.1 b/doc/haproxy.1
index 001de15..48717ad 100644
--- a/doc/haproxy.1
+++ b/doc/haproxy.1
@@ -57,6 +57,10 @@ starting up.
 Start in daemon mode.
 
 .TP
+\fB\-Ds\fP
+Start in systemd daemon mode, keeping a process in foreground.
+
+.TP
 \fB\-q\fP
 Disable messages on output.
 
diff --git a/include/types/global.h b/include/types/global.h
index 133a98d..730cc64 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -42,6 +42,7 @@
 #defineMODE_VERBOSE0x10
 #defineMODE_STARTING   0x20
 #defineMODE_FOREGROUND 0x40
+#defineMODE_SYSTEMD0x80
 
 /* list of last checks to perform, depending on config options */
 #define LSTCHK_CAP_BIND0x0001  /* check that we can bind to 
any port */
diff --git a/src/haproxy.c b/src/haproxy.c
index 4503a01..92e25c2 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -42,6 +42,7 @@
 #include signal.h
 #include stdarg.h
 #include sys/resource.h
+#include sys/wait.h
 #include time.h
 #include syslog.h
 #include grp.h
@@ -539,8 +540,11 @@ void init(int argc, char **argv)
arg_mode |= MODE_DEBUG;
else if (*flag == 'c')
arg_mode |= MODE_CHECK;
-   else if (*flag == 'D')
+   else if (*flag == 'D') {
arg_mode |= MODE_DAEMON;
+   if (flag[1] == 's')  /* -Ds */
+   arg_mode |= MODE_SYSTEMD;
+   }
else if (*flag == 'q')
arg_mode |= MODE_QUIET;
else if (*flag == 's'  (flag[1] == 'f' || flag[1] == 
't')) {
@@ -594,7 +598,7 @@ void init(int argc, char **argv)
}
 
global.mode = MODE_STARTING | /* during startup, we want most of the 
alerts */
-   (arg_mode  (MODE_DAEMON | MODE_FOREGROUND | MODE_VERBOSE
+   (arg_mode  (MODE_DAEMON | MODE_SYSTEMD | MODE_FOREGROUND | 
MODE_VERBOSE
 | MODE_QUIET | MODE_CHECK | MODE_DEBUG));
 
if (LIST_ISEMPTY(cfg_cfgfiles))
@@ -733,24 +737,24 @@ void init(int argc, char **argv)
 
if (arg_mode  (MODE_DEBUG | MODE_FOREGROUND)) {
/* command line debug mode inhibits configuration mode */
-   global.mode = ~(MODE_DAEMON | MODE_QUIET);
+   global.mode = ~(MODE_DAEMON | MODE_SYSTEMD | MODE_QUIET);
global.mode |= (arg_mode  (MODE_DEBUG | MODE_FOREGROUND));
}
 
-   if (arg_mode  MODE_DAEMON) {
+   if (arg_mode  (MODE_DAEMON | MODE_SYSTEMD)) {
/* command line daemon mode inhibits foreground and debug modes 
mode */
global.mode = ~(MODE_DEBUG | MODE_FOREGROUND);
-   global.mode |= (arg_mode  MODE_DAEMON);
+   global.mode |= (arg_mode  (MODE_DAEMON | MODE_SYSTEMD));
}
 
global.mode |= (arg_mode  (MODE_QUIET | MODE_VERBOSE));
 
-   if ((global.mode  MODE_DEBUG)  (global.mode  (MODE_DAEMON | 
MODE_QUIET))) {
-   Warning(debug mode incompatible with quiet and daemon. 
Keeping debug only.\n);
-   global.mode = ~(MODE_DAEMON | MODE_QUIET);
+   if ((global.mode  MODE_DEBUG

[[V2] 2/3] MEDIUM: add haproxy-systemd-wrapper

2013-02-12 Thread Marc-Antoine Perennou
Currently, to reload haproxy configuration, you have to use -sf.

There is a problem with this way of doing things. First of all, in the systemd 
world,
reload commands should be oneshot ones, which means they should not be the 
new main
process but rather a tool which makes a call to it and then exits. With the 
current approach,
the reload command is the new main command and moreover, it makes the previous 
one exit.
Systemd only tracks the main program, seeing it ending, it assumes it either 
finished or failed,
and kills everything remaining as a grabage collector. We then end up with no 
haproxy running
at all.

This patch adds wrapper around haproxy, no changes at all have been made into 
it,
so it's not intrusive and doesn't change anything for other hosts. What this 
wrapper does
is basically launching haproxy as a child, listen to the SIGUSR2 (not to 
conflict with
haproxy itself) signal, and spawing a new haproxy with -sf as a child to 
relay the
first one.

Signed-off-by: Marc-Antoine Perennou marc-anto...@perennou.com
---
 .gitignore|   1 +
 Makefile  |  16 +-
 src/haproxy-systemd-wrapper.c | 113 ++
 3 files changed, 128 insertions(+), 2 deletions(-)
 create mode 100644 src/haproxy-systemd-wrapper.c

diff --git a/.gitignore b/.gitignore
index 5d9576a..5e6f556 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@ src/*.o
 *.log*
 *.trace*
 haproxy-*
+!src/*.c
 make-*
 dlmalloc.c
 00*.patch
diff --git a/Makefile b/Makefile
index f1eed55..ca9e1b2 100644
--- a/Makefile
+++ b/Makefile
@@ -593,7 +593,7 @@ all:
@echo
@exit 1
 else
-all: haproxy
+all: haproxy haproxy-systemd-wrapper
 endif
 
 OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocol.o \
@@ -618,12 +618,17 @@ ifneq ($(TRACE),)
 OBJS += src/trace.o
 endif
 
+WRAPPER_OBJS = src/haproxy-systemd-wrapper.o
+
 # Not used right now
 LIB_EBTREE = $(EBTREE_DIR)/libebtree.a
 
 haproxy: $(OBJS) $(OPTIONS_OBJS) $(EBTREE_OBJS)
$(LD) $(LDFLAGS) -o $@ $^ $(LDOPTS)
 
+haproxy-systemd-wrapper: $(WRAPPER_OBJS)
+   $(LD) $(LDFLAGS) -o $@ $^ $(LDOPTS)
+
 $(LIB_EBTREE): $(EBTREE_OBJS)
$(AR) rv $@ $^
 
@@ -646,6 +651,11 @@ src/haproxy.o: src/haproxy.c
  -DBUILD_OPTIONS='$(strip $(BUILD_OPTIONS))' \
   -c -o $@ $
 
+src/haproxy-systemd-wrapper.o: src/haproxy-systemd-wrapper.c
+   $(CC) $(COPTS) \
+ -DSBINDIR='$(strip $(SBINDIR))' \
+  -c -o $@ $
+
 src/dlmalloc.o: $(DLMALLOC_SRC)
$(CC) $(COPTS) -DDEFAULT_MMAP_THRESHOLD=$(DLMALLOC_THRES) -c -o $@ $
 
@@ -659,9 +669,10 @@ install-doc:
install -m 644 doc/$$x.txt $(DESTDIR)$(DOCDIR) ; \
done
 
-install-bin: haproxy
+install-bin: haproxy haproxy-systemd-wrapper
install -d $(DESTDIR)$(SBINDIR)
install haproxy $(DESTDIR)$(SBINDIR)
+   install haproxy-systemd-wrapper $(DESTDIR)$(SBINDIR)
 
 install: install-bin install-man install-doc
 
@@ -670,6 +681,7 @@ clean:
for dir in . src include/* doc ebtree; do rm -f $$dir/*~ $$dir/*.rej 
$$dir/core; done
rm -f haproxy-$(VERSION).tar.gz haproxy-$(VERSION)$(SUBVERS).tar.gz
rm -f haproxy-$(VERSION) nohup.out gmon.out
+   rm -f haproxy-systemd-wrapper
 
 tags:
find src include \( -name '*.c' -o -name '*.h' \) -print0 | \
diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c
new file mode 100644
index 000..57e8d7d
--- /dev/null
+++ b/src/haproxy-systemd-wrapper.c
@@ -0,0 +1,113 @@
+/*
+ * Wrapper to make haproxy systemd-compliant.
+ *
+ * Copyright 2013 Marc-Antoine Perennou marc-anto...@perennou.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include errno.h
+#include signal.h
+#include stdbool.h
+#include stdio.h
+#include stdlib.h
+#include string.h
+#include unistd.h
+#include sys/wait.h
+
+static pid_t pid = 0;
+static char *pid_file = /run/haproxy.pid;
+static int main_argc;
+static char **main_argv;
+
+static pid_t spawn_haproxy(char **pid_strv, int nb_pid)
+{
+   pid_t pid = fork();
+   if (!pid) {
+   /* 3 for haproxy -Ds -sf */
+   char **argv = calloc(4 + main_argc + nb_pid + 1, sizeof(char 
*));
+   int i;
+   int argno = 0;
+   argv[argno++] = SBINDIR/haproxy;
+   for (i = 0; i  main_argc; ++i)
+   argv[argno++] = main_argv[i];
+   argv[argno++] = -Ds;
+   if (nb_pid  0) {
+   argv[argno++] = -sf;
+   for (i = 0; i  nb_pid; ++i)
+   argv[argno++] = pid_strv[i];
+   }
+   argv[argno] = NULL;
+   execv(argv[0], argv

[[V2] 3/3] MEDIUM: add systemd service

2013-02-12 Thread Marc-Antoine Perennou
Signed-off-by: Marc-Antoine Perennou marc-anto...@perennou.com
---
 .gitignore |  1 +
 Makefile   |  8 ++--
 contrib/systemd/haproxy.service.in | 11 +++
 3 files changed, 18 insertions(+), 2 deletions(-)
 create mode 100644 contrib/systemd/haproxy.service.in

diff --git a/.gitignore b/.gitignore
index 5e6f556..ec1545a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,4 @@ haproxy-*
 make-*
 dlmalloc.c
 00*.patch
+*.service
diff --git a/Makefile b/Makefile
index ca9e1b2..1b81fc7 100644
--- a/Makefile
+++ b/Makefile
@@ -593,7 +593,7 @@ all:
@echo
@exit 1
 else
-all: haproxy haproxy-systemd-wrapper
+all: haproxy haproxy-systemd-wrapper systemd/haproxy.service
 endif
 
 OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocol.o \
@@ -659,6 +659,10 @@ src/haproxy-systemd-wrapper.o: 
src/haproxy-systemd-wrapper.c
 src/dlmalloc.o: $(DLMALLOC_SRC)
$(CC) $(COPTS) -DDEFAULT_MMAP_THRESHOLD=$(DLMALLOC_THRES) -c -o $@ $
 
+systemd/haproxy.service: contrib/systemd/haproxy.service.in
+   mkdir -p systemd
+   sed -e 's:@SBINDIR@:'$(strip $(SBINDIR))':' $  $@
+
 install-man:
install -d $(DESTDIR)$(MANDIR)/man1
install -m 644 doc/haproxy.1 $(DESTDIR)$(MANDIR)/man1
@@ -681,7 +685,7 @@ clean:
for dir in . src include/* doc ebtree; do rm -f $$dir/*~ $$dir/*.rej 
$$dir/core; done
rm -f haproxy-$(VERSION).tar.gz haproxy-$(VERSION)$(SUBVERS).tar.gz
rm -f haproxy-$(VERSION) nohup.out gmon.out
-   rm -f haproxy-systemd-wrapper
+   rm -f haproxy-systemd-wrapper systemd/haproxy.service
 
 tags:
find src include \( -name '*.c' -o -name '*.h' \) -print0 | \
diff --git a/contrib/systemd/haproxy.service.in 
b/contrib/systemd/haproxy.service.in
new file mode 100644
index 000..f925651
--- /dev/null
+++ b/contrib/systemd/haproxy.service.in
@@ -0,0 +1,11 @@
+[Unit]
+Description=HAProxy Load Balancer
+After=network.target
+
+[Service]
+ExecStart=@SBINDIR@/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p 
/run/haproxy.pid
+ExecReload=/usr/bin/kill -USR2 $MAINPID
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
-- 
1.8.1.2




Re: [PATCH 1/3] MEDIUM: New cli option -Ds for systemd compatibility

2013-02-09 Thread Marc-Antoine Perennou
On 9 February 2013 09:45, Willy Tarreau w...@1wt.eu wrote:

 On Fri, Feb 08, 2013 at 03:58:46PM +0100, Marc-Antoine Perennou wrote:
  @@ -1493,8 +1499,13 @@ int main(int argc, char **argv)
px = px-next;
}
 
  - if (proc == global.nbproc)
  + if (proc == global.nbproc) {
  + if (global.mode  MODE_SYSTEMD) {
  + for (proc = 0; proc  global.nbproc;
 proc++)
  + waitpid(children[proc], NULL, 0);
  + }
exit(0); /* parent must leave */
  + }
 
/* if we're NOT in QUIET mode, we should now close the 3
 first FDs to ensure
 * that we can detach from the TTY. We MUST NOT do it in
 other cases since

 I think we have an issue here, which should not be too hard to fix. The
 parent is the one which binds to all the ports, so here it still owns
 them. This means that a soft restart of a new process will fail until
 the parent leaves, since it will not release these ports. And the parent
 will not leave until all of its children have terminated. Or maybe I'm
 missing something :-/

 Also wouldn't it be worth catching EINTR here in the loop ? Otherwise
 I fear that random signals sent to the process will make the for loop
 progress to next child eventhough previous ones are not dead. This can
 easily happen during debugging sessions (ctrl-Z/bg) or when people
 mistakenly send a SIGHUP to the old process.

 Willy



I just made a simple test, running a webserver serving a big file locally,
using haproxy,
my wrapper and systemd service. I started a download and during this
download,
reloaded haproxy. I using nbproc = 2.
What happened ?
When I started haproxy, I ended up with a wrapper launching a child
launching itself
two children, we'll call them ha1, ha11 and ha12. Then when I reloaded, the
wrapper
launched a new child which launched two new children, ha2, ha21 and ha22.
ha11 and thus ha1 were still there until the download had finished, ha12
got to zombie state.
ha2, ha21 and ha22 successfully have shown up and take all new connections.
Once the download has finished, ha11 exited, ha12 too (waitpid making it
leave the zombie state)
and then ha11, leaving us with only ha2, ha21 and ha22.
I think this is the expected behaviour, so there don't seem to be any bug
here.

For the EINTR stuff, I'm not sure at all, not really familiar with it, so I
will give it a look


Re: [PATCH 2/3] MEDIUM: add haproxy-systemd-wrapper

2013-02-09 Thread Marc-Antoine Perennou
I'll do even simpler, when submitting V2 of this patchset with the EINTR
issue,
I'll basically forard every arg given to the wrapper to all the children
themselves.
The tool is not really meant to be used by the user himself though, but
rather to
be launched by the systemd service.
Is SIGUSR2 ok here ? I first did it with SIGUSR1 but then children couldn't
bind
to this signal on reload, since it was already a USR1 action, so I took the
first one
not colliding.


On 9 February 2013 09:49, Willy Tarreau w...@1wt.eu wrote:

 On Fri, Feb 08, 2013 at 03:58:47PM +0100, Marc-Antoine Perennou wrote:
  +static void usage(const char *progname)
  +{
  + fprintf(stderr, Usage: %s [-f cfgfile] [-p pidfile]\n, progname);

 Here I think it would be worth supporting most of the other command line
 arguments. For instance, -L is mandatory when session replication is
 enabled
 between multiple peers. -C is used by people who have to load many ACLs or
 certs and want to chdir there to load the files. -c is handy to validate
 configurations so that they don't have to switch between two different
 tools
 and syntaxes. I think we can ignore the various debugging flags now
 however.

 Regards,
 Willy




Re: [PATCH 1/3] MEDIUM: New cli option -Ds for systemd compatibility

2013-02-09 Thread Marc-Antoine Perennou
On 9 February 2013 11:06, Willy Tarreau w...@1wt.eu wrote:

 Hi,

 On Sat, Feb 09, 2013 at 10:44:04AM +0100, Marc-Antoine Perennou wrote:
  I just made a simple test, running a webserver serving a big file
 locally,
  using haproxy,
  my wrapper and systemd service. I started a download and during this
  download,
  reloaded haproxy. I using nbproc = 2.
  What happened ?
  When I started haproxy, I ended up with a wrapper launching a child
  launching itself
  two children, we'll call them ha1, ha11 and ha12. Then when I reloaded,
 the
  wrapper
  launched a new child which launched two new children, ha2, ha21 and ha22.
  ha11 and thus ha1 were still there until the download had finished, ha12
  got to zombie state.

 Then if ha1 was still there, I don't understand how it did not prevent the
 new process from binding to the port. Could you please check ha1 is still
 bound to the port once the process runs ? That's what I don't understand.

  ha2, ha21 and ha22 successfully have shown up and take all new
 connections.
  Once the download has finished, ha11 exited, ha12 too (waitpid making it
  leave the zombie state)
  and then ha11, leaving us with only ha2, ha21 and ha22.
  I think this is the expected behaviour, so there don't seem to be any bug
  here.

 Yes it's the expected behaviour, but I don't understand *why* it works, so
 it is very possible that we're having a bug somewhere else making this work
 as a side effect.

  For the EINTR stuff, I'm not sure at all, not really familiar with it,
 so I
  will give it a look

 Typically I would replace :

  waitpid(pid, NULL, 0);

 with

  while (waitpid(pid, NULL, 0) == -1  errno == EINTR);

 For instance, when your process receives SIGTTOU/SIGTTIN upon a failed
 attempt of a new process to start, the old one very likely skips a few
 children (one per signal).

 If it can help you, here's how to test for the worst case :

   - have a running process with a simple configuration bound to one port :

 listen foo
  bind :8000

   - then have a second configuration which will not work due to a double
 bind on the same port, and another bind on the first port :

 listen foo
  bind :8000

 listen fail1
  bind :8001

 listen fail2
  bind :8001

   - when the first one is running, try to start the second one. It will
 fail to bind to :8000, will send a SIGTTOU to process 1 and try again.
 Then it will fail to bind :8001 without knowing it's not because of #1,
 so it will wait a bit, believing it's #1 which has not yet released it,
 and then it will abort, sending SIGTTIN to #1 to inform it that it
 gives
 up and that #1 must continue its job as if nothing happened.

   - process 1 should then just remain unaffected. And restarting #1 with
 the fail2 listener commented out should work as expected.

 Best regards,
 Willy


Maybe this can help you understand why it works:

Before the download:
haproxy   6090 root4u IPv4  53819  0t0 TCP
*:http (LISTEN)
haproxy   6092 root4u IPv4  53819  0t0 TCP
*:http (LISTEN)
haproxy   6093 root4u IPv4  53819  0t0 TCP
*:http (LISTEN)

During the download:
haproxy   6090 root4u IPv4  53819  0t0 TCP
*:http (LISTEN)
haproxy   6092 root4u IPv4  53819  0t0 TCP
*:http (LISTEN)
haproxy   6093 root1u IPv4  57972  0t0 TCP
Lou.local:http-Lou.local:40395 (ESTABLISHED)
haproxy   6093 root4u IPv4  53819  0t0 TCP
*:http (LISTEN)

During the download, after the reload:
haproxy   6093 root1u IPv4  57972  0t0 TCP
Lou.local:http-Lou.local:40395 (ESTABLISHED)
haproxy   6239 root4u IPv4  54622  0t0 TCP
*:http (LISTEN)
haproxy   6240 root4u IPv4  54622  0t0 TCP
*:http (LISTEN)
haproxy   6241 root4u IPv4  54622  0t0 TCP
*:http (LISTEN)

After the download:
haproxy   6239 root4u IPv4  54622  0t0 TCP
*:http (LISTEN)
haproxy   6240 root4u IPv4  54622  0t0 TCP
*:http (LISTEN)
haproxy   6241 root4u IPv4  54622  0t0 TCP
*:http (LISTEN)


[PATCH 2/3] MEDIUM: add haproxy-systemd-wrapper

2013-02-08 Thread Marc-Antoine Perennou
Signed-off-by: Marc-Antoine Perennou marc-anto...@perennou.com
---
 .gitignore|   1 +
 Makefile  |  16 +-
 src/haproxy-systemd-wrapper.c | 122 ++
 3 files changed, 137 insertions(+), 2 deletions(-)
 create mode 100644 src/haproxy-systemd-wrapper.c

diff --git a/.gitignore b/.gitignore
index 5d9576a..5e6f556 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@ src/*.o
 *.log*
 *.trace*
 haproxy-*
+!src/*.c
 make-*
 dlmalloc.c
 00*.patch
diff --git a/Makefile b/Makefile
index f1eed55..ca9e1b2 100644
--- a/Makefile
+++ b/Makefile
@@ -593,7 +593,7 @@ all:
@echo
@exit 1
 else
-all: haproxy
+all: haproxy haproxy-systemd-wrapper
 endif
 
 OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocol.o \
@@ -618,12 +618,17 @@ ifneq ($(TRACE),)
 OBJS += src/trace.o
 endif
 
+WRAPPER_OBJS = src/haproxy-systemd-wrapper.o
+
 # Not used right now
 LIB_EBTREE = $(EBTREE_DIR)/libebtree.a
 
 haproxy: $(OBJS) $(OPTIONS_OBJS) $(EBTREE_OBJS)
$(LD) $(LDFLAGS) -o $@ $^ $(LDOPTS)
 
+haproxy-systemd-wrapper: $(WRAPPER_OBJS)
+   $(LD) $(LDFLAGS) -o $@ $^ $(LDOPTS)
+
 $(LIB_EBTREE): $(EBTREE_OBJS)
$(AR) rv $@ $^
 
@@ -646,6 +651,11 @@ src/haproxy.o: src/haproxy.c
  -DBUILD_OPTIONS='$(strip $(BUILD_OPTIONS))' \
   -c -o $@ $
 
+src/haproxy-systemd-wrapper.o: src/haproxy-systemd-wrapper.c
+   $(CC) $(COPTS) \
+ -DSBINDIR='$(strip $(SBINDIR))' \
+  -c -o $@ $
+
 src/dlmalloc.o: $(DLMALLOC_SRC)
$(CC) $(COPTS) -DDEFAULT_MMAP_THRESHOLD=$(DLMALLOC_THRES) -c -o $@ $
 
@@ -659,9 +669,10 @@ install-doc:
install -m 644 doc/$$x.txt $(DESTDIR)$(DOCDIR) ; \
done
 
-install-bin: haproxy
+install-bin: haproxy haproxy-systemd-wrapper
install -d $(DESTDIR)$(SBINDIR)
install haproxy $(DESTDIR)$(SBINDIR)
+   install haproxy-systemd-wrapper $(DESTDIR)$(SBINDIR)
 
 install: install-bin install-man install-doc
 
@@ -670,6 +681,7 @@ clean:
for dir in . src include/* doc ebtree; do rm -f $$dir/*~ $$dir/*.rej 
$$dir/core; done
rm -f haproxy-$(VERSION).tar.gz haproxy-$(VERSION)$(SUBVERS).tar.gz
rm -f haproxy-$(VERSION) nohup.out gmon.out
+   rm -f haproxy-systemd-wrapper
 
 tags:
find src include \( -name '*.c' -o -name '*.h' \) -print0 | \
diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c
new file mode 100644
index 000..aa509f6
--- /dev/null
+++ b/src/haproxy-systemd-wrapper.c
@@ -0,0 +1,122 @@
+/*
+ * Wrapper to make haproxy systemd-compliant.
+ *
+ * Copyright 2013 Marc-Antoine Perennou marc-anto...@perennou.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include limits.h
+#include signal.h
+#include stdarg.h
+#include stdbool.h
+#include stdio.h
+#include stdlib.h
+#include string.h
+#include unistd.h
+#include sys/wait.h
+
+#define MAX_ARGS 10
+
+static pid_t pid = 0;
+static const char *conf_file = /etc/haproxy/haproxy.cfg;
+static const char *pid_file = /run/haproxy.pid;
+
+static pid_t exec_bg(char **pid_strv, int nb_pid, char *arg, ...)
+{
+   pid_t pid = fork();
+   if (!pid) {
+   char **argv = calloc(MAX_ARGS + nb_pid + 1, sizeof(char *));
+   int i;
+   int argno = 0;
+   va_list al;
+   va_start(al, arg);
+   while (arg  argno  MAX_ARGS + 1) {
+   argv[argno++] = arg;
+   arg = va_arg(al, char *);
+   }
+   va_end (al);
+   for (i = 0; i  nb_pid; ++i)
+   argv[argno++] = pid_strv[i];
+   argv[argno] = NULL;
+   execv(argv[0], argv);
+   exit(0);
+   } else return pid;
+}
+
+static int read_pids(char ***pid_strv)
+{
+   FILE *f = fopen(pid_file, r);
+   int read = 0, allocated = 8;
+   char pid_str[10];
+
+   if (!f)
+   return 0;
+
+   *pid_strv = malloc(allocated * sizeof(char *));
+   while (1 == fscanf(f, %s\n, pid_str)) {
+   if (read == allocated) {
+   allocated *= 2;
+   *pid_strv = realloc(*pid_strv, allocated * sizeof(char 
*));
+   }
+   (*pid_strv)[read++] = strdup(pid_str);
+   }
+
+   fclose(f);
+
+   return read;
+}
+
+static void signal_handler(int signum __attribute__((unused)))
+{
+   int i;
+   char **pid_strv = NULL;
+   int nb_pid = read_pids(pid_strv);
+
+   pid = exec_bg(pid_strv, nb_pid, SBINDIR/haproxy, -Ds, -f, 
conf_file, -p, pid_file, -sf, NULL);
+
+   for (i = 0; i  nb_pid; ++i)
+   free(pid_strv[i]);
+   free(pid_strv

HAProxy and systemd compatibility

2013-02-08 Thread Marc-Antoine Perennou
Hi,

Currently, to reload haproxy configuration, you have to use -sf.

Systemd philosophy is for the daemon not to fork by themselves, but rather let
the init process do it for them.

My first patch adds a new option -Ds which is exactly like -D, but instead 
of
forking n times to get n jobs running and then exiting, prefers to wait for all 
the
children it just created. With this done, haproxy becomes more 
systemd-compliant,
without changing anything for other systems.

Now comes a problem with the -sf way to do things. First of all, in the 
systemd world,
reload commands should be oneshot ones, which means they should not be the 
new main
process but rather a tool which makes a call to it and then exits. With the 
current approach,
the reload command is the new main command and moreover, it makes the previous 
one exit.
Systemd only tracks the main program, seeing it ending, it assumes it either 
finished or failed,
and kills everything remaining as a grabage collector. We then end up with no 
haproxy running 
at all.

My second patch is a wrapper around haproxy, no changes at all have been made 
into it,
so it's not intrusive and doesn't change anything for other hosts. What this 
wrapper does
is basically launching haproxy as a child, listen to the SIGUSR2 (not to 
conflict with
haproxy itself) signal, and spawing a new haproxy with -sf as a child to 
relay the
first one.

The third patch is a logical continuation to the two first ones, providing a 
systemd service file.




[PATCH 1/3] MEDIUM: New cli option -Ds for systemd compatibility

2013-02-08 Thread Marc-Antoine Perennou
Signed-off-by: Marc-Antoine Perennou marc-anto...@perennou.com
---
 doc/haproxy-en.txt |  1 +
 doc/haproxy-fr.txt |  1 +
 doc/haproxy.1  |  4 
 include/types/global.h |  1 +
 src/haproxy.c  | 35 +++
 5 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/doc/haproxy-en.txt b/doc/haproxy-en.txt
index 3d2a2be..4c673d3 100644
--- a/doc/haproxy-en.txt
+++ b/doc/haproxy-en.txt
@@ -51,6 +51,7 @@ There are only a few command line options :
= 'maxconn' in 'listen' or 'default' sections
 -d starts in foregreound with debugging mode enabled
 -D starts in daemon mode
+-Ds starts in systemd daemon mode
 -q disable messages on output
 -V displays messages on output even when -q or 'quiet' are specified.
 -c only checks config file and exits with code 0 if no error was found, or
diff --git a/doc/haproxy-fr.txt b/doc/haproxy-fr.txt
index 87bb972..0e36724 100644
--- a/doc/haproxy-fr.txt
+++ b/doc/haproxy-fr.txt
@@ -53,6 +53,7 @@ Les options de lancement sont peu nombreuses :
= 'maxconn' dans les sections 'listen' ou 'default'
 -d active le mode debug
 -D passe en daemon
+-Ds passe en daemon systemd
 -q d�sactive l'affichage de messages sur la sortie standard.
 -V affiche les messages sur la sortie standard, m�me si -q ou 'quiet' sont
sp�cifi�s.
diff --git a/doc/haproxy.1 b/doc/haproxy.1
index 001de15..48717ad 100644
--- a/doc/haproxy.1
+++ b/doc/haproxy.1
@@ -57,6 +57,10 @@ starting up.
 Start in daemon mode.
 
 .TP
+\fB\-Ds\fP
+Start in systemd daemon mode, keeping a process in foreground.
+
+.TP
 \fB\-q\fP
 Disable messages on output.
 
diff --git a/include/types/global.h b/include/types/global.h
index 133a98d..730cc64 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -42,6 +42,7 @@
 #defineMODE_VERBOSE0x10
 #defineMODE_STARTING   0x20
 #defineMODE_FOREGROUND 0x40
+#defineMODE_SYSTEMD0x80
 
 /* list of last checks to perform, depending on config options */
 #define LSTCHK_CAP_BIND0x0001  /* check that we can bind to 
any port */
diff --git a/src/haproxy.c b/src/haproxy.c
index 4503a01..75ebd52 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -42,6 +42,7 @@
 #include signal.h
 #include stdarg.h
 #include sys/resource.h
+#include sys/wait.h
 #include time.h
 #include syslog.h
 #include grp.h
@@ -539,8 +540,11 @@ void init(int argc, char **argv)
arg_mode |= MODE_DEBUG;
else if (*flag == 'c')
arg_mode |= MODE_CHECK;
-   else if (*flag == 'D')
+   else if (*flag == 'D') {
arg_mode |= MODE_DAEMON;
+   if (flag[1] == 's')  /* -Ds */
+   arg_mode |= MODE_SYSTEMD;
+   }
else if (*flag == 'q')
arg_mode |= MODE_QUIET;
else if (*flag == 's'  (flag[1] == 'f' || flag[1] == 
't')) {
@@ -594,7 +598,7 @@ void init(int argc, char **argv)
}
 
global.mode = MODE_STARTING | /* during startup, we want most of the 
alerts */
-   (arg_mode  (MODE_DAEMON | MODE_FOREGROUND | MODE_VERBOSE
+   (arg_mode  (MODE_DAEMON | MODE_SYSTEMD | MODE_FOREGROUND | 
MODE_VERBOSE
 | MODE_QUIET | MODE_CHECK | MODE_DEBUG));
 
if (LIST_ISEMPTY(cfg_cfgfiles))
@@ -733,24 +737,24 @@ void init(int argc, char **argv)
 
if (arg_mode  (MODE_DEBUG | MODE_FOREGROUND)) {
/* command line debug mode inhibits configuration mode */
-   global.mode = ~(MODE_DAEMON | MODE_QUIET);
+   global.mode = ~(MODE_DAEMON | MODE_SYSTEMD | MODE_QUIET);
global.mode |= (arg_mode  (MODE_DEBUG | MODE_FOREGROUND));
}
 
-   if (arg_mode  MODE_DAEMON) {
+   if (arg_mode  (MODE_DAEMON | MODE_SYSTEMD)) {
/* command line daemon mode inhibits foreground and debug modes 
mode */
global.mode = ~(MODE_DEBUG | MODE_FOREGROUND);
-   global.mode |= (arg_mode  MODE_DAEMON);
+   global.mode |= (arg_mode  (MODE_DAEMON | MODE_SYSTEMD));
}
 
global.mode |= (arg_mode  (MODE_QUIET | MODE_VERBOSE));
 
-   if ((global.mode  MODE_DEBUG)  (global.mode  (MODE_DAEMON | 
MODE_QUIET))) {
-   Warning(debug mode incompatible with quiet and daemon. 
Keeping debug only.\n);
-   global.mode = ~(MODE_DAEMON | MODE_QUIET);
+   if ((global.mode  MODE_DEBUG)  (global.mode  (MODE_DAEMON | 
MODE_SYSTEMD | MODE_QUIET))) {
+   Warning(debug mode incompatible with quiet, daemon and 
systemd. Keeping debug only.\n);
+   global.mode = ~(MODE_DAEMON | MODE_SYSTEMD | MODE_QUIET);
}
 
-   if ((global.nbproc  1

[PATCH 3/3] MEDIUM: add systemd service

2013-02-08 Thread Marc-Antoine Perennou
Signed-off-by: Marc-Antoine Perennou marc-anto...@perennou.com
---
 .gitignore |  1 +
 Makefile   |  8 ++--
 contrib/systemd/haproxy.service.in | 11 +++
 3 files changed, 18 insertions(+), 2 deletions(-)
 create mode 100644 contrib/systemd/haproxy.service.in

diff --git a/.gitignore b/.gitignore
index 5e6f556..ec1545a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,4 @@ haproxy-*
 make-*
 dlmalloc.c
 00*.patch
+*.service
diff --git a/Makefile b/Makefile
index ca9e1b2..1b81fc7 100644
--- a/Makefile
+++ b/Makefile
@@ -593,7 +593,7 @@ all:
@echo
@exit 1
 else
-all: haproxy haproxy-systemd-wrapper
+all: haproxy haproxy-systemd-wrapper systemd/haproxy.service
 endif
 
 OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocol.o \
@@ -659,6 +659,10 @@ src/haproxy-systemd-wrapper.o: 
src/haproxy-systemd-wrapper.c
 src/dlmalloc.o: $(DLMALLOC_SRC)
$(CC) $(COPTS) -DDEFAULT_MMAP_THRESHOLD=$(DLMALLOC_THRES) -c -o $@ $
 
+systemd/haproxy.service: contrib/systemd/haproxy.service.in
+   mkdir -p systemd
+   sed -e 's:@SBINDIR@:'$(strip $(SBINDIR))':' $  $@
+
 install-man:
install -d $(DESTDIR)$(MANDIR)/man1
install -m 644 doc/haproxy.1 $(DESTDIR)$(MANDIR)/man1
@@ -681,7 +685,7 @@ clean:
for dir in . src include/* doc ebtree; do rm -f $$dir/*~ $$dir/*.rej 
$$dir/core; done
rm -f haproxy-$(VERSION).tar.gz haproxy-$(VERSION)$(SUBVERS).tar.gz
rm -f haproxy-$(VERSION) nohup.out gmon.out
-   rm -f haproxy-systemd-wrapper
+   rm -f haproxy-systemd-wrapper systemd/haproxy.service
 
 tags:
find src include \( -name '*.c' -o -name '*.h' \) -print0 | \
diff --git a/contrib/systemd/haproxy.service.in 
b/contrib/systemd/haproxy.service.in
new file mode 100644
index 000..f925651
--- /dev/null
+++ b/contrib/systemd/haproxy.service.in
@@ -0,0 +1,11 @@
+[Unit]
+Description=HAProxy Load Balancer
+After=network.target
+
+[Service]
+ExecStart=@SBINDIR@/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p 
/run/haproxy.pid
+ExecReload=/usr/bin/kill -USR2 $MAINPID
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
-- 
1.8.1.2




Re: -sf/-st not working

2013-02-07 Thread Marc-Antoine Perennou
It is totally normal that systemd kills the new process as the main one
which was the first has exited. This is the expected behaviour.

I'm currently patching haproxy to fully support systemd, I'll probably
submit my patches by tomorrow (It's fully functionnal here, only needs a
little cleaning)


On 7 February 2013 16:31, Eugene Istomin e.isto...@edss.ee wrote:

 **

 I think the main problem is in systemd:



 - from commandline -sf working as expected

 - from sysvinit -sf working as expected

 - from systemd -sf only stop process.



 I try both init.d  systemd scripts in systemd-based linux - all results
 are the same:



 Loaded: loaded (/lib/systemd/system/haproxy.service; disabled)

 Active: failed (Result: signal) since Thu, 07 Feb 2013 17:18:43 +0200;
 12s ago

 Process: 28125 ExecReload=/usr/sbin/haproxy -D -f
 /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid -sf $MAINPID (code=exited,
 status=0/SUCCESS)

 Process: 28118 ExecStart=/usr/sbin/haproxy -D -f /etc/haproxy/haproxy.cfg
 -p /var/run/haproxy.pid (code=exited, status=0/SUCCESS)

 Process: 28115 ExecStartPre=/usr/sbin/haproxy -c -q -f
 /etc/haproxy/haproxy.cfg (code=exited, status=0/SUCCESS)

 Main PID: 28126 (code=killed, signal=KILL)

 CGroup: name=systemd:/system/haproxy.service





 systemd script:

 [Unit]

 Description=HAProxy For TCP And HTTP Based Applications

 After=network.target



 [Service]

 Type=forking

 PIDFile=/var/run/haproxy.pid

 ExecStartPre=/usr/sbin/haproxy -c -q -f /etc/haproxy/haproxy.cfg

 ExecStart=/usr/sbin/haproxy -D -f /etc/haproxy/haproxy.cfg -p
 /var/run/haproxy.pid

 ExecReload=/usr/sbin/haproxy -D -f /etc/haproxy/haproxy.cfg -p
 /var/run/haproxy.pid -sf $MAINPID



 [Install]

 WantedBy=multi-user.target



 --

 Best regards,

 Eugene Istomin




 On Thursday 07 February 2013 14:07:44 Baptiste wrote:

  You should have a new HAProxy process started using the new

  configuration and binding the ports...

 

  cheers

 

  On 2/7/13, Eugene Istomin e.isto...@edss.ee wrote:

   Thanks for the answer,

  

   as written in

   http://www.mgoff.in/2010/04/18/haproxy-reloading-your-config-with-

   minimal-service-impact/

   The end-result is a reload of the configuration file which is not
 visible

   by

   the customer

  

   But in our case it leads to unbinding from all ports and finishing
 haproxy

   process.

   Can this issue related to rpm build options? RPM build log is

  
 https://build.opensuse.org/package/rawlog?arch=x86_64package=haproxy-1.5;

   project=server%3Ahttprepository=openSUSE_12.2

  

  

   --

   Best regards,

   Eugene Istomin

  

   On Thursday 07 February 2013 07:28:17 Willy Tarreau wrote:

   Hello Eugene,

  

   On Wed, Feb 06, 2013 at 08:29:33PM +0200, Eugene Istomin wrote:

Hello,

   

We have problem with reload/HUP:

if i run #/usr/sbin/haproxy -D -f /etc/haproxy/haproxy.cfg -p

/var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid) - haproxy
 process

is

shutting down and exit

  

   This is the intended behaviour, it unbinds from its ports so that the
 new

   process can bind, then waits for all existing connections to terminate

   and leaves. Isn't it what you're observing ? What would you have
 expected

   instead ?

  

   Willy



[PATCH] MEDIUM: New cli option -Ds for systemd compatibility

2012-11-07 Thread Marc-Antoine Perennou
Signed-off-by: Marc-Antoine Perennou marc-anto...@perennou.com
---
 doc/haproxy-en.txt |  1 +
 doc/haproxy-fr.txt |  1 +
 doc/haproxy.1  |  4 
 include/types/global.h |  1 +
 src/haproxy.c  | 31 +++
 5 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/doc/haproxy-en.txt b/doc/haproxy-en.txt
index 6a7aa01..e54c714 100644
--- a/doc/haproxy-en.txt
+++ b/doc/haproxy-en.txt
@@ -51,6 +51,7 @@ There are only a few command line options :
= 'maxconn' in 'listen' or 'default' sections
 -d starts in foregreound with debugging mode enabled
 -D starts in daemon mode
+-Ds starts in systemd daemon mode
 -q disable messages on output
 -V displays messages on output even when -q or 'quiet' are specified.
 -c only checks config file and exits with code 0 if no error was found, or
diff --git a/doc/haproxy-fr.txt b/doc/haproxy-fr.txt
index 89df8cb..85f4168 100644
--- a/doc/haproxy-fr.txt
+++ b/doc/haproxy-fr.txt
@@ -53,6 +53,7 @@ Les options de lancement sont peu nombreuses :
= 'maxconn' dans les sections 'listen' ou 'default'
 -d active le mode debug
 -D passe en daemon
+-Ds passe en daemon systemd
 -q d�sactive l'affichage de messages sur la sortie standard.
 -V affiche les messages sur la sortie standard, m�me si -q ou 'quiet' sont
sp�cifi�s.
diff --git a/doc/haproxy.1 b/doc/haproxy.1
index 001de15..48717ad 100644
--- a/doc/haproxy.1
+++ b/doc/haproxy.1
@@ -57,6 +57,10 @@ starting up.
 Start in daemon mode.
 
 .TP
+\fB\-Ds\fP
+Start in systemd daemon mode, keeping a process in foreground.
+
+.TP
 \fB\-q\fP
 Disable messages on output.
 
diff --git a/include/types/global.h b/include/types/global.h
index 28632b7..f6e0eac 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -42,6 +42,7 @@
 #defineMODE_VERBOSE0x10
 #defineMODE_STARTING   0x20
 #defineMODE_FOREGROUND 0x40
+#defineMODE_SYSTEMD0x80
 
 /* list of last checks to perform, depending on config options */
 #define LSTCHK_CAP_BIND0x0001  /* check that we can bind to 
any port */
diff --git a/src/haproxy.c b/src/haproxy.c
index c6933c3..b7430f8 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -42,6 +42,7 @@
 #include signal.h
 #include stdarg.h
 #include sys/resource.h
+#include sys/wait.h
 #include time.h
 #include syslog.h
 
@@ -509,8 +510,11 @@ void init(int argc, char **argv)
arg_mode |= MODE_DEBUG;
else if (*flag == 'c')
arg_mode |= MODE_CHECK;
-   else if (*flag == 'D')
+   else if (*flag == 'D') {
arg_mode |= MODE_DAEMON;
+   if (flag[1] == 's')  /* -Ds */
+   arg_mode |= MODE_SYSTEMD;
+   }
else if (*flag == 'q')
arg_mode |= MODE_QUIET;
else if (*flag == 's'  (flag[1] == 'f' || flag[1] == 
't')) {
@@ -564,7 +568,7 @@ void init(int argc, char **argv)
}
 
global.mode = MODE_STARTING | /* during startup, we want most of the 
alerts */
-   (arg_mode  (MODE_DAEMON | MODE_FOREGROUND | MODE_VERBOSE
+   (arg_mode  (MODE_DAEMON | MODE_SYSTEMD | MODE_FOREGROUND | 
MODE_VERBOSE
 | MODE_QUIET | MODE_CHECK | MODE_DEBUG));
 
if (LIST_ISEMPTY(cfg_cfgfiles))
@@ -715,24 +719,24 @@ void init(int argc, char **argv)
 
if (arg_mode  (MODE_DEBUG | MODE_FOREGROUND)) {
/* command line debug mode inhibits configuration mode */
-   global.mode = ~(MODE_DAEMON | MODE_QUIET);
+   global.mode = ~(MODE_DAEMON | MODE_SYSTEMD | MODE_QUIET);
global.mode |= (arg_mode  (MODE_DEBUG | MODE_FOREGROUND));
}
 
-   if (arg_mode  MODE_DAEMON) {
+   if (arg_mode  (MODE_DAEMON | MODE_SYSTEMD)) {
/* command line daemon mode inhibits foreground and debug modes 
mode */
global.mode = ~(MODE_DEBUG | MODE_FOREGROUND);
-   global.mode |= (arg_mode  MODE_DAEMON);
+   global.mode |= (arg_mode  (MODE_DAEMON | MODE_SYSTEMD));
}
 
global.mode |= (arg_mode  (MODE_QUIET | MODE_VERBOSE));
 
-   if ((global.mode  MODE_DEBUG)  (global.mode  (MODE_DAEMON | 
MODE_QUIET))) {
-   Warning(debug mode incompatible with quiet and daemon. 
Keeping debug only.\n);
-   global.mode = ~(MODE_DAEMON | MODE_QUIET);
+   if ((global.mode  MODE_DEBUG)  (global.mode  (MODE_DAEMON | 
MODE_SYSTEMD | MODE_QUIET))) {
+   Warning(debug mode incompatible with quiet, daemon and 
systemd. Keeping debug only.\n);
+   global.mode = ~(MODE_DAEMON | MODE_SYSTEMD | MODE_QUIET);
}
 
-   if ((global.nbproc  1)  !(global.mode  MODE_DAEMON