diff --git a/Readme.md b/Readme.md
index f61f8461749284a50e5e27227923db94c96c2332..320c93ae9563b0d3b23daf93bedf21975ddb13d3 100644
--- a/Readme.md
+++ b/Readme.md
@@ -28,9 +28,9 @@
 + [X] Dictionnaires:
     + [X] Francais
     + [X] Noms
-+ [ ] Packages
-+ [ ] Installeur
-+ [ ] Service systemd
++ [X] Packages
++ [X] Installeur
++ [X] Service systemd
 + [ ] Tests
 
 ## Licences
diff --git a/src/apache/pass-checker.conf b/passchecker/apache/pass-checker.conf
similarity index 80%
rename from src/apache/pass-checker.conf
rename to passchecker/apache/pass-checker.conf
index d06b7b49e1c83b73fe3d04253ee4e921b71737a4..26b5d6338d09ac30ac3ca81c931ac9c393e014e9 100644
--- a/src/apache/pass-checker.conf
+++ b/passchecker/apache/pass-checker.conf
@@ -8,8 +8,8 @@
 
     ProxyVia On
     ProxyRequests Off
-    ProxyPass / http://localhost:8842/
-    ProxyPassReverse / http://localhost:8842/
+    ProxyPass / http://localhost:8842/cgi-bin/index.py
+    ProxyPassReverse / http://localhost:8842/cgi-bin/index.py
     ProxyPreserveHost on
     <Proxy *>
         Options FollowSymLinks MultiViews
diff --git a/src/index.py b/passchecker/cgi-bin/index.py
similarity index 92%
rename from src/index.py
rename to passchecker/cgi-bin/index.py
index 5fda04d2a43ba235e4654f4edff0b6b50aea33f5..53811b22dec78defb0c4089e1af7f0ea56017ac5 100755
--- a/src/index.py
+++ b/passchecker/cgi-bin/index.py
@@ -19,7 +19,7 @@
 import cgi
 import re
 from markdown import markdown
-from test_pass import test_pass
+from passchecker.lib.zxcvbn_wrapper import test_pass
 
 form = cgi.FieldStorage()
 print("Content-type: text/html; charset=utf-8\n")
@@ -28,14 +28,14 @@ html = """<!DOCTYPE html>
 <head>
 <meta charset="UTF-8">
 <meta name="author" content="David Beniamine">
-<link type="text/css" rel="stylesheet" href="css/style.css" />
+<link type="text/css" rel="stylesheet" href="/web/css/style.css" />
 <title>Tetras Pass</title>
 </head>
 <body>
 <div id="box">
 <div id="content">
 <div id="logos">
-<img style="float:left" src="img/tl.png" alt="Tetras Libre" />
+<img style="float:left" src="/web/img/tl.png" alt="Tetras Libre" />
 <h1>
 Tetras Pass
 </h1>
@@ -51,7 +51,7 @@ if form.getvalue("password") is None:
     sendPrompt = "Lancer le test"
 
     html += """
-        <form action="/index.py" method="post" id="mainform">
+        <form action="/cgi-bin/index.py" method="post" id="mainform">
             <div id="form">
             <h2> Defenseur.se </h2>
             <p> {} </p>
diff --git a/src/commands/cli.py b/passchecker/commands/cli.py
similarity index 96%
rename from src/commands/cli.py
rename to passchecker/commands/cli.py
index 40fbcbc42f55f2d8c54ee23fd18050a06b2fb7ca..eda5e4bc7be06fb63b03c0c285ad9385e0a76b85 100644
--- a/src/commands/cli.py
+++ b/passchecker/commands/cli.py
@@ -17,7 +17,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from getpass import getpass
-from test_pass import test_pass
+from ..lib.zxcvbn_wrapper import test_pass
 
 
 def cli():
diff --git a/passchecker/commands/passcheckerdefaults.py b/passchecker/commands/passcheckerdefaults.py
new file mode 100644
index 0000000000000000000000000000000000000000..6576afb201fd72c7c9bec102d78a238f438a5856
--- /dev/null
+++ b/passchecker/commands/passcheckerdefaults.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+# coding: utf-8
+# Copyright (C) 2017 Beniamine, David <David@Beniamine.net>
+# Author: Beniamine, David <David@Beniamine.net>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+PASS_CHECKER_DEFAULTS = {
+    'server': False,
+    'port': 8842,
+    'address': "localhost",
+}
diff --git a/src/commands/web.py b/passchecker/commands/web.py
similarity index 73%
rename from src/commands/web.py
rename to passchecker/commands/web.py
index 36a1f6994c86416cd6a7c62872ea199330ec07ac..95c8c8032e21e4f8ce898304e01139d11b66cb66 100644
--- a/src/commands/web.py
+++ b/passchecker/commands/web.py
@@ -18,20 +18,20 @@
 
 from http.server import HTTPServer
 from http.server import CGIHTTPRequestHandler
-import cgi
-import cgitb
+from .passcheckerdefaults import PASS_CHECKER_DEFAULTS
 
-cgitb.enable()
 
-def serve(addr, port):
-    server_address = (addr, port)
+def server(address=PASS_CHECKER_DEFAULTS['address'], port=PASS_CHECKER_DEFAULTS['port']):
+    server_address = (address, port)
     server = HTTPServer
     handler = CGIHTTPRequestHandler
-    handler.cgi_directories = ["/"]
-    print("Serveur actif sur le port :", port)
+    print("Server up and running at: http://{}:{}/cgi-bin/index.py".format(address,port))
 
     httpd = server(server_address, handler)
-    httpd.serve_forever()
+    try:
+        httpd.serve_forever()
+    except KeyboardInterrupt:
+        httpd.socket.close()
 
 if __name__ == "__main__":
-    serve("localhost", 8080)
+    server()
diff --git a/data/Prenoms.txt b/passchecker/lib/data/Prenoms.txt
similarity index 100%
rename from data/Prenoms.txt
rename to passchecker/lib/data/Prenoms.txt
diff --git a/data/francais.txt b/passchecker/lib/data/francais.txt
similarity index 100%
rename from data/francais.txt
rename to passchecker/lib/data/francais.txt
diff --git a/src/lib/translations.py b/passchecker/lib/translations.py
similarity index 100%
rename from src/lib/translations.py
rename to passchecker/lib/translations.py
diff --git a/src/lib/zxcvbn-wrapper.py b/passchecker/lib/zxcvbn_wrapper.py
similarity index 97%
rename from src/lib/zxcvbn-wrapper.py
rename to passchecker/lib/zxcvbn_wrapper.py
index c951158ef56d8cf7daa55f9526ac4f548cbffb5d..3971deccfaf31747c9979db7f81a691de25ddb28 100644
--- a/src/lib/zxcvbn-wrapper.py
+++ b/passchecker/lib/zxcvbn_wrapper.py
@@ -16,12 +16,13 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from pkg_resources import resource_listdir
 import os
 from dateutil.parser import parse
 from itertools import combinations
 from zxcvbn import zxcvbn
 from zxcvbn.matching import add_frequency_lists
-from translations import tr
+from .translations import tr
 
 comments = {
     'offline_fast_hashing_1e10_per_second':
@@ -39,8 +40,8 @@ comments = {
 
 def add_dictionnaries():
     dicts = {}
-    directory = os.path.dirname(os.path.realpath(__file__))+'/../data'
-    for fn in os.listdir(directory):
+    directory = 'data'
+    for fn in resource_listdir(__name__, directory):
         fn = directory+"/"+fn
         if os.path.isfile(fn):
             name = os.path.basename(os.path.splitext(fn)[0])
diff --git a/passchecker/passchecker.py b/passchecker/passchecker.py
new file mode 100644
index 0000000000000000000000000000000000000000..e0771f8d53d4ad29d9b55c03c508aead03c90d30
--- /dev/null
+++ b/passchecker/passchecker.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+# coding: utf-8
+
+import click
+
+from .commands.passcheckerdefaults import PASS_CHECKER_DEFAULTS
+from .commands.cli import cli
+from .commands.web import server
+
+@click.command(help="Run passchecker")
+@click.option('--web/--no-web',
+              default=PASS_CHECKER_DEFAULTS['server'],
+              help='Start the server for web interface, no means use CLI')
+@click.option('--port',
+              default=PASS_CHECKER_DEFAULTS['port'],
+              help='Port on which the web server should listen')
+@click.option('--address',
+              default=PASS_CHECKER_DEFAULTS['address'],
+              help='Address on which the web server should listen')
+def passchecker(web, port, address):
+    if web:
+        server(address=address,port=port)
+    else:
+        if port != PASS_CHECKER_DEFAULTS['port']:
+            print('--port option has no sense without --web, ignoring')
+        if address != PASS_CHECKER_DEFAULTS['address']:
+            print('--address option has no sense without --web, ignoring')
+        cli()
+
+if __name__ == '__main__':
+    passchecker()
diff --git a/src/service/pass-checker.service b/passchecker/service/pass-checker.service
similarity index 100%
rename from src/service/pass-checker.service
rename to passchecker/service/pass-checker.service
diff --git a/src/css/style.css b/passchecker/web/css/style.css
similarity index 100%
rename from src/css/style.css
rename to passchecker/web/css/style.css
diff --git a/src/img/tl.png b/passchecker/web/img/tl.png
similarity index 100%
rename from src/img/tl.png
rename to passchecker/web/img/tl.png
diff --git a/setup.py b/setup.py
index b67b8d21fd26a94f8a6aa178bfe62cb10f4a4ba0..3bd0166a2693045c95acc0e7956003b9f5ff7c16 100644
--- a/setup.py
+++ b/setup.py
@@ -3,19 +3,23 @@
 
 from setuptools import setup, find_packages
 
+NAME = "passchecker"
+
 setup(
-    name="Pass-Checker",
+    name=NAME,
     version="0.1",
     packages=find_packages(),
-    scripts=['pass-checker.py'],
-
+    package_dir={NAME: NAME},
+    entry_points={
+        'console_scripts':
+        ['passchecker = passchecker.passchecker:passchecker']
+    },
     # Project uses reStructuredText, so ensure that the docutils get
     # installed or upgraded on the target machine
-    install_requires=['click', 'zxcvbn', 'http.server', 'cgi', 'cgitb', 'getpass'],
+    install_requires=['click', 'zxcvbn-python>=4.4.14'],
 
     package_data={
-        # If any package contains *.txt or *.rst files, include them:
-        '': ['*.txt', '*.rst'],
+        '': ['*.txt'],
     },
 
     # metadata for upload to PyPI
diff --git a/src/pass-checker.py b/src/pass-checker.py
deleted file mode 100644
index b5ea76015434b6a693a5f5a15421e64303211e6c..0000000000000000000000000000000000000000
--- a/src/pass-checker.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env python3
-# coding: utf-8
-
-import click
-from server import serve
-from console import cli
-
-@click.option('--server/--no-server', default=False, help='Start the server for web interface, no means use CLI')
-@click.option('--port', default=8842, help='Port on which the web server should listen')
-@click.option('--address', default='localhost', help='Address on which the web server should listen')
-def passchecker(server, port, address):
-
-
-if __name__ == '__main__':
-    passchecker()