{"id":354,"date":"2023-01-06T22:23:51","date_gmt":"2023-01-06T22:23:51","guid":{"rendered":"https:\/\/cloasdata.de\/?p=354"},"modified":"2023-01-06T22:23:51","modified_gmt":"2023-01-06T22:23:51","slug":"run-you-own-pypi-repository-local-on-raspberry-pi","status":"publish","type":"post","link":"https:\/\/cloasdata.de\/?p=354","title":{"rendered":"Run you own pypi repository local on raspberry pi."},"content":{"rendered":"\n<p>Sometimes you want to run your own and local python repository. For example you want to manage your development projects within your LAN environment without using a public repository. <\/p>\n\n\n\n<p>Before doing it by copying from dev machine to production machine and install it from bare it might be a good idea to use <a href=\"https:\/\/pypi.org\/project\/pypiserver\" data-type=\"URL\" data-id=\"https:\/\/pypi.org\/project\/pypiserver\">pypi-server<\/a> as a local repository, making pip you dependency manager as you normally also would do.<br><br>This short post is based on the very good docs of <a href=\"https:\/\/pypi.org\/project\/pypiserver\" data-type=\"URL\" data-id=\"https:\/\/pypi.org\/project\/pypiserver\">pypi-server<\/a> and adds some further information.  I also found that the docs is a bit outdated. <br><br>In this example I&#8217;m installing a server on a raspberry pi 3. Dependencies for this are running python 3 interpreter, working virtual environment, working pip. S<br><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Running python 3 interpreter: <code>python3 --version<\/code><\/li>\n\n\n\n<li>Working virtual environment: <code>python -m venv --help<\/code><\/li>\n\n\n\n<li>Working pip: <code>pip --version<\/code><\/li>\n\n\n\n<li>Some basic knowledge in <a href=\"https:\/\/setuptools.pypa.io\/en\/latest\/userguide\/index.html\" data-type=\"URL\" data-id=\"https:\/\/setuptools.pypa.io\/en\/latest\/userguide\/index.html\">python package distribution<\/a> might help as well.<\/li>\n<\/ul>\n\n\n\n<p>First we start on our rpi with updating it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">sudo apt update\nsudo apt upgrade<\/code><\/pre>\n\n\n\n<p>Then we should check if venv is running and doing things the right way. <strong>Please note no superuser do (sudo)<\/strong>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">mkdir app\ncd app\nmkdir pypiserver\npython3 -m venv .\/pypiserver<\/code><\/pre>\n\n\n\n<p>This will create a fresh virtual environment. There should be no error. Now we can activate the venv and install pypiserver.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">cd pypiserver\nsource .\/bin\/activate\npip install pypiserver passlib<\/code><\/pre>\n\n\n\n<p>pypiserver is now installed. We also installed passlib to handle login\/identification. Now we need a container for the packages and see if the server script is working<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">mkdir packages\npypi-server --version\n> 1.5.1<\/code><\/pre>\n\n\n\n<p>Before starting serving packages we need to add a possibility to upload packages via twine or setuptools (both are recommended) instead of placing the packages directly into the above packages directory.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">htpasswd -sc htpasswd.txt pypiuser<\/code><\/pre>\n\n\n\n<p>You will be prompted for a password string then. If htpasswd is not you can either install apache2 (<code>sudo apt install apache2<\/code>) or generate password file manual via <a href=\"https:\/\/hostingcanada.org\/htpasswd-generator\/\">https:\/\/hostingcanada.org\/htpasswd-generator\/<\/a>.<\/p>\n\n\n\n<p>We are now ready to serve.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">pypi-server run -p 8080 -P htpasswd.txt .\/packages &amp;<\/code><\/pre>\n\n\n\n<p>You can check also from now via http:\/\/localhost:8080 if server is okay. You should see something similar like<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"642\" height=\"328\" src=\"https:\/\/cloasdata.de\/wp-content\/uploads\/2023\/01\/image.png\" alt=\"\" class=\"wp-image-362\" srcset=\"https:\/\/cloasdata.de\/wp-content\/uploads\/2023\/01\/image.png 642w, https:\/\/cloasdata.de\/wp-content\/uploads\/2023\/01\/image-300x153.png 300w\" sizes=\"auto, (max-width: 642px) 100vw, 642px\" \/><\/figure>\n\n\n\n<p>Now we could try to upload our first package to local pypi. My typical tool chain to build and upload a python package looks like following shell commands (Assuming a complete setup.cfg and pyproject.toml in the root folder. More can be found <a href=\"https:\/\/setuptools.pypa.io\/en\/latest\/userguide\/declarative_config.html\">here<\/a>).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">python -m build -o .\/build\ntwine check build\/*\ntwine upload --verbose --repository-url http:\/\/xxx.xxx.xxx.xx:8080 build\/* -u pypiuser -p apasswordphrase<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"550\" height=\"271\" src=\"https:\/\/cloasdata.de\/wp-content\/uploads\/2023\/01\/image-1.png\" alt=\"\" class=\"wp-image-363\" srcset=\"https:\/\/cloasdata.de\/wp-content\/uploads\/2023\/01\/image-1.png 550w, https:\/\/cloasdata.de\/wp-content\/uploads\/2023\/01\/image-1-300x148.png 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><figcaption class=\"wp-element-caption\">Successful distributed a python package <\/figcaption><\/figure>\n\n\n\n<p>And now you could convince pip to install that package from the local repository. We are doing a dry run here.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">pip install --index-url http:\/\/192.168.178.22:8080 --trusted-host 192.168.178.22:8080 PACKAGENAME --dry-run<\/code><\/pre>\n\n\n\n<p>That was quiet easy and you now can distribute packages locally with the benefits of pip. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sometimes you want to run your own and local python repository. For example you want to manage your development projects within your LAN environment without using a public repository. Before doing it by copying from dev machine to production machine and install it from bare it might be a good idea to use pypi-server as [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":364,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[4],"tags":[18,17,5,16],"class_list":["post-354","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-pip","tag-pypi","tag-python","tag-raspberry-pi"],"_links":{"self":[{"href":"https:\/\/cloasdata.de\/index.php?rest_route=\/wp\/v2\/posts\/354","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloasdata.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloasdata.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloasdata.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cloasdata.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=354"}],"version-history":[{"count":3,"href":"https:\/\/cloasdata.de\/index.php?rest_route=\/wp\/v2\/posts\/354\/revisions"}],"predecessor-version":[{"id":366,"href":"https:\/\/cloasdata.de\/index.php?rest_route=\/wp\/v2\/posts\/354\/revisions\/366"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloasdata.de\/index.php?rest_route=\/wp\/v2\/media\/364"}],"wp:attachment":[{"href":"https:\/\/cloasdata.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=354"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloasdata.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=354"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloasdata.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=354"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}