{"id":17720192,"url":"https://github.com/mpolinowski/http-fileserver-kubernetes","last_synced_at":"2025-07-22T11:39:36.762Z","repository":{"id":37588853,"uuid":"175651856","full_name":"mpolinowski/http-fileserver-kubernetes","owner":"mpolinowski","description":"Using Docker to create a static file server for an Kubernetes Cluster","archived":false,"fork":false,"pushed_at":"2019-04-22T09:33:22.000Z","size":193,"stargazers_count":20,"open_issues_count":0,"forks_count":5,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-07T21:45:57.425Z","etag":null,"topics":["docker","file-server","kubernetes","nginx","nginx-docker"],"latest_commit_sha":null,"homepage":null,"language":"Dockerfile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mpolinowski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-03-14T15:42:09.000Z","updated_at":"2024-02-13T22:18:05.000Z","dependencies_parsed_at":"2022-08-25T13:12:38.854Z","dependency_job_id":null,"html_url":"https://github.com/mpolinowski/http-fileserver-kubernetes","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mpolinowski/http-fileserver-kubernetes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpolinowski%2Fhttp-fileserver-kubernetes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpolinowski%2Fhttp-fileserver-kubernetes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpolinowski%2Fhttp-fileserver-kubernetes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpolinowski%2Fhttp-fileserver-kubernetes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mpolinowski","download_url":"https://codeload.github.com/mpolinowski/http-fileserver-kubernetes/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpolinowski%2Fhttp-fileserver-kubernetes/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266486471,"owners_count":23936968,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","file-server","kubernetes","nginx","nginx-docker"],"created_at":"2024-10-25T15:26:30.140Z","updated_at":"2025-07-22T11:39:36.730Z","avatar_url":"https://github.com/mpolinowski.png","language":"Dockerfile","funding_links":[],"categories":["Dockerfile"],"sub_categories":[],"readme":"```\n????????????????????????????????????????????????????????????????????????????????????????????????????\n????????????????????????????????????????????????????????????????????????????????????????????????????\n????????????????????????????????????????????????%..%????????????????????????????????????????????????\n??????????????????????????????????????????????%.....,???????????????????????????????????????????????\n?????????????????????????????????????????????,.........?????????????????????????????????????????????\n??????????????????????????????????????????;..............:??????????????????????????????????????????\n????????????????????????????????????????;..................:????????????????????????????????????????\n??????????????????????????????????????:......................,??????????????????????????????????????\n????????????????????????????????????:...........................????????????????????????????????????\n??????????????????????????????????...............,:...............??????????????????????????????????\n????????????????????????????????.................??,................????????????????????????????????\n??????????????????????????????,..................??..................,??????????????????????????????\n????????????????????????????,....................??,....................????????????????????????????\n???????????????????????????......................??......................???????????????????????????\n???????????????????????????......................??......................???????????????????????????\n???????????????????????????...................,,????,,...................???????????????????????????\n??????????????????????????+.................????????????.........,........??????????????????????????\n??????????????????????????.......*?%......%??????????????%......??%......,??????????????????????????\n??????????????????????????.......????....???????+??????????....*??%.......??????????????????????????\n??????????????????????????........+??*.,?????...,???...?????,,???*........%?????????????????????????\n??????????????????????????.........,???????.....+???.....%??????..........:?????????????????????????\n?????????????????????????............?????......????......?????,..........,?????????????????????????\n?????????????????????????,...........?????;.....????.....:?????............?????????????????????????\n?????????????????????????............???????....????....%??????,...........?????????????????????????\n?????????????????????????...........???*%????...????...?????;???...........?????????????????????????\n????????????????????????:...........%??..????%%+?????%?????.,???............????????????????????????\n????????????????????????...........*??%...???????????????%...*??%...........????????????????????????\n????????????????????????...........???.....;????????????*.....???...........????????????????????????\n????????????????????????...........???......:??????????*......???...........????????????????????????\n???????????????????????+...........??%......:???....????......???,...........???????????????????????\n???????????????????????............???....??????....??????....???............???????????????????????\n???????????????????????............???,%%???????....?????????:???,...........???????????????????????\n???????????????????????............??????????????%???????????????............???????????????????????\n???????????????????????.........,????????????%?????????????????????:.,.......;??????????????????????\n??????????????????????.......,?????????,......????????,....,.?????????*......,??????????????????????\n??????????????????????,.......??*...???.......????????,......???...:??,......,??????????????????????\n??????????????????????..............????.....%???.,????.....,??%..............??????????????????????\n??????????????????????,..............???.....???%..*???.....???:..............??????????????????????\n???????????????????????..............????...????....???%...????..............???????????????????????\n???????????????????????%..............???%..???;.....??%..????..............????????????????????????\n????????????????????????;..............????,??%,.....%??+????,.............,????????????????????????\n?????????????????????????...............??????,.......??????:.............,?????????????????????????\n??????????????????????????,.............,????????++????????...............??????????????????????????\n???????????????????????????..............,%???????????????...............???????????????????????????\n????????????????????????????..............???%?????????%??..............*???????????????????????????\n????????????????????????????;.............??..,,??%?,..,%?,............,????????????????????????????\n?????????????????????????????............??.............,??............%????????????????????????????\n??????????????????????????????..........,??..............%?*..........??????????????????????????????\n???????????????????????????????.........%?%..............+??.........???????????????????????????????\n????????????????????????????????........,?,...............*.........????????????????????????????????\n????????????????????????????????*..................................:%???????????????????????????????\n?????????????????????????????????.................................,?????????????????????????????????\n??????????????????????????????????,...............................??????????????????????????????????\n???????????????????????????????????..............................%??????????????????????????????????\n????????????????????????????????????............................%???????????????????????????????????\n?????????????????????????????????????.........................,+????????????????????????????????????\n??????????????????????????????????????........................??????????????????????????????????????\n????????????????????????????????????????????????????????????????????????????????????????????????????\n????????????????????????????????????????????????????????????????????????????????????????????????????\n```\n\n\n\n\u003c!-- TOC --\u003e\n\n- [Kubernetes HTTP Fileserver](#kubernetes-http-fileserver)\n  - [Serving static files from inside a Docker Container](#serving-static-files-from-inside-a-docker-container)\n  - [Serving static files from a PersistentVolume (Recommended)](#serving-static-files-from-a-persistentvolume-recommended)\n    - [Create a PersistentVolume](#create-a-persistentvolume)\n    - [Create a PersistentVolumeClaim](#create-a-persistentvolumeclaim)\n    - [Create a Pod](#create-a-pod)\n    - [Creating the Service](#creating-the-service)\n    - [Troubleshooting a Service](#troubleshooting-a-service)\n    - [Adding it to our NGINX Ingress](#adding-it-to-our-nginx-ingress)\n    - [Deployment](#deployment)\n    - [Troubleshooting the NGINX Ingress](#troubleshooting-the-nginx-ingress)\n    - [Adding TLS to your Ingress](#adding-tls-to-your-ingress)\n    - [Volume Access Control](#volume-access-control)\n\n\u003c!-- /TOC --\u003e\n\n\n\n# Kubernetes HTTP Fileserver\n\n## Serving static files from inside a Docker Container\n\n1. Create a Dockerfile to work with the [official NGINX Docker Container](https://hub.docker.com/_/nginx) that will copy all the content from the __download folder__ to the __public directory__ of the NGINX server:\n\n\n```yaml\nFROM nginx\nCOPY downloads/ /usr/share/nginx/html\n```\n\n\n2. Build the image and tag it for your Docker repository:\n\n\n```bash\ndocker build -t my-docker-hub-account/http-fileserver-kubernetes .\n```\n\n\n3. (Optional) Test run your container:\n\n\n```bash\ndocker run -d -p 8080:80 my-docker-hub-account/http-fileserver-kubernetes\n```\n\nYou should now be able to access the files you stored inside the __downloads folder__ via `http://localhost:8080/dl/test.txt` (assuming that you used the __downloads__ folder from the repository, that contains a sub directory __dl__ that contains a text file __test.txt__):\n\n\n![Kubernetes](./image_01.png)\n\n\n\n4. Push the Docker Image to Docker hub\n\n\n```bash\ndocker login\ndocker push my-docker-hub-account/http-fileserver-kubernetes\n```\n\n\nAlternatively, do your build on the host system where you want to run the image - so the image is in local storage. This is a __hacky solution__ that is not fully supported - if you don't want to push your image to the Docker Hub, you are supposed to use a local/personal registry for your Docker images. That feels a little bit much for my problem here - so I will proceed with this way.\n\n__Note__: if you want to use the local image, you have to build the image on every Node server that you are using in Kubernetes and that might be used to spawn the pod. You also have to set the `imagePullPolicy= Never` (see YAML file in the next step)! This will make sure that Kubernetes will always use the image from local storage instead of trying to pull it from Docker Hub.\n\n\n\n5. Creating the Kubernetes Deployment\n\n\n```yaml\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  creationTimestamp: null\n  labels:\n    service: http-fileserver\n  name: http-fileserver\nspec:\n  replicas: 1\n  strategy: {}\n  template:\n    metadata:\n      creationTimestamp: null\n      labels:\n        service: http-fileserver\n    spec:\n      containers:\n      - image: my-docker-hub-account/http-fileserver-kubernetes:latest\n        imagePullPolicy: Always\n        name: http-fileserver\n        resources: {}\n      restartPolicy: Always\nstatus: {}\n\n---\n\napiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    service: http-fileserver\n  name: http-fileserver\nspec:\n  ports:\n    - name: http\n      port: 80\n  selector:\n    service: http-fileserver\nstatus:\n  loadBalancer: {}\n```\n\n\nAlternatively use a simple pod, instead of a deployment:\n\n\n\n```yaml\nkind: Pod\napiVersion: v1\nmetadata:\n  name: http-fileserver\n  labels:\n    app: fileserver\nspec:\n  containers:\n    - name: http-fileserver\n      image: my-docker-hub-account/http-fileserver-kubernetes:latest\n      imagePullPolicy: Always\n      ports:\n        - containerPort: 80\n\n---\n\nkind: Service\napiVersion: v1\nmetadata:\n  name: http-fileserver\nspec:\n  selector:\n    app: fileserver\n  ports:\n    - port: 80\n```\n\n\n\n6. You can run the deployment (or pod) by the Kubernetes command - see [Kubernetes Ingress](https://mpolinowski.github.io/kubernetes-nginx-ingress/):\n\n\n\n```bash\nkubectl create -f http-fileserver.yaml\n```\n\n\n![Kubernetes](./image_02.png)\n\n\n\n\n## Serving static files from a PersistentVolume (Recommended)\n\nIf all you have to serve are a few text files, the above solution will be sufficient. But what if we are talking about a large quantity of files you want to make available over the internet? Adding your files to a persistent storage and linking it to all services that need to have access to it will be the way to go.\n\n\nTo accomplish this we need to do the following tasks:\n\n1. Create a __PersistentVolume__ that is backed by physical storage but is not associate with any Pod.\n2. Create a __PersistentVolumeClaim__, which gets automatically bound to a suitable __PersistentVolume__.\n3. Create a __Pod__ that uses the __PersistentVolumeClaim__ as storage.\n\n\n### Create a PersistentVolume\n\nLet's start with creating a folder that is going to hold our files, e.g. `/opt/filecontainer/dl`, and a file to it that you want to serve:\n\n\n```js\nmkdir /opt/filecontainer/dl\necho 'This is a test' \u003e /opt/filecontainer/dl/index.txt\n```\n\n\nWe will create a __hostPath PersistentVolume__. Kubernetes supports hostPath for development and testing on a single-node cluster. A hostPath PersistentVolume uses a file or directory on the Node to emulate network-attached storage (see Google Compute Engine persistent disk, an NFS share, or an Amazon Elastic Block Store volume instead if you are using the corresponding cloud solutions).\n\n\nThe configuration file for the hostPath PersistentVolume looks like this:\n\n\n__file-storage-pv.yaml__\n\n```yaml\nkind: PersistentVolume\napiVersion: v1\nmetadata:\n  name: file-storage-volume\n  labels:\n    type: local\nspec:\n  storageClassName: manual\n  capacity:\n    storage: 5Gi\n  accessModes:\n    - ReadWriteOnce\n  hostPath:\n    path: \"/opt/filecontainer\"\n```\n\u003c!-- /opt/http-fileserver/downloads --\u003e\n\n\nThe configuration file specifies that the volume is at `/opt/filecontainer` on the cluster’s Node. The configuration also specifies a size of _3Gi_ and an access mode of _ReadWriteOnce_, which means the volume can be mounted as read-write by a single Node. It defines the StorageClass name manual for the PersistentVolume, which will be used to bind PersistentVolumeClaim requests to this PersistentVolume.\n\n\nCreate the PersistentVolume:\n\n\n```bash\nkubectl apply -f file-storage-pv.yaml\nkubectl get pv file-storage-volume\n```\n\n\n![Kubernetes](./image_03.png)\n\n\nThe output shows that the PersistentVolume has a STATUS of Available.\n\n\n### Create a PersistentVolumeClaim\n\nThe next step is to create a __PersistentVolumeClaim__. Pods use PersistentVolumeClaims to request physical storage. In this exercise, you create a PersistentVolumeClaim that requests a volume of at least three gigs that can provide read-write access for at least one Node.\n\nHere is the configuration file for the PersistentVolumeClaim:\n\n\n__file-storage-pvc.yaml__\n\n```yaml\nkind: PersistentVolumeClaim\napiVersion: v1\nmetadata:\n  name: file-storage-claim\nspec:\n  storageClassName: manual\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 3Gi\n```\n\n\nAfter you create the PersistentVolumeClaim, the Kubernetes control plane looks for a PersistentVolume that satisfies the claim’s requirements. If the control plane finds a suitable PersistentVolume with the same StorageClass, it binds the claim to the volume.\n\n\n```bash\nkubectl apply -f file-storage-pvc.yaml\nkubectl get pv file-storage-volume\n```\n\n\n![Kubernetes](./image_04.png)\n\n\nNow the output shows a STATUS of Bound.\n\n\n\n### Create a Pod\n\nThe next step is to create a Pod that uses your PersistentVolumeClaim as a volume.\n\nHere is the configuration file for the Pod:\n\n\n__file-storage-pod.yaml__\n\n```yaml\nkind: Pod\napiVersion: v1\nmetadata:\n  name: file-storage\n  labels:\n    app: file-storage\nspec:\n  volumes:\n    - name: file-storage-volume\n      persistentVolumeClaim:\n       claimName: file-storage-claim\n  containers:\n    - name: file-storage-container\n      image: nginx\n      ports:\n        - containerPort: 80\n          name: file-storage\n      volumeMounts:\n        - mountPath: \"/usr/share/nginx/html\"\n          name: file-storage-volume\n```\n\n\nCreate the Pod and verify that the Container in the Pod is running:\n\n\n```bash\nkubectl create -f file-storage-pod.yaml\nkubectl exec -it file-storage -- /bin/bash\n```\n\n\n![Kubernetes](./image_05.png)\n\n\nWe can see that our `/opt/filecontainer` folder was successfully mounted to `/usr/share/nginx/html` !\n\nWe can also test if NGINX is running and serving our content by installing `curl` inside the container and checking if the file is available on localhost:\n\n\n```bash\napt update\napt install curl\ncurl http://localhost/dl/index.txt\n```\n\n\n![Kubernetes](./image_06.png)\n\n\nThe file we created is being served by the NGINX web service!\n\n\n\n### Creating the Service\n\nTo access the pod we first have to create a service that point to it:\n\n\n__file-storage-service.yaml__\n\n```yaml\napiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    app: file-storage\n  name: file-storage\nspec:\n  ports:\n    - name: http\n      port: 80\n  selector:\n    app: file-storage\nstatus:\n  loadBalancer: {}\n```\n\n\n### Troubleshooting a Service\n\nI am returning here after noticing that the Ingress, I am going to add in the next step, does not seem to work. We already tested that the pod we created is running, has the PersistentVolume mounted and is hosting our content - so maybe the service is not attached to the pod?\n\nWhat happens if a Service does not seem to work? We can follow the [Kubernetes Debug Guide](https://kubernetes.io/docs/tasks/debug-application-cluster/debug-service/) to check where the issue lies.\n\n\nWe can start by checking if the pod we created can be found by it's label\n\n\n```bash\nkubectl get pods -l app=file-storage\n```\n\n\nAssuming you have another Pod that already consumes the Service by name you would get something like:\n\n\n```bash\nwget -O- file-storage\nResolving file-storage (file-storage)... failed: Name or service not known.\nwget: unable to resolve host address ‘file-storage’\n```\n\n\nSo the first thing to check is whether that Service actually exists:\n\n\n```bash\nkubectl get svc file-storage\nNAME           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE\nfile-storage   ClusterIP   10.102.5.116   \u003cnone\u003e        80/TCP    14h\n```\n\n\n![Kubernetes](./image_07.png)\n\n\nThe Pod is available, the service is running, but we are not getting access to the service using the `wget` command. Also a `curl file-storage:80/dl/test.txt` fails - is there something wrong with the DNS resolution?\n\n\nTrying to access the pod through the service works without a hitch, when using the Cluster IP address:\n\n\n```bash\ncurl 10.102.5.116:80/dl/test.txt\n```\n\n\n![Kubernetes](./image_08.png)\n\n\n\nI am turning a bit in circles now - the __POD__ can be selected by the same label the __SERVICE__ is using to find the service (`app=file-storage`). The service correctly uses the as __ENDPOINT__ `kubectl get endpoints file-storage` (`10.32.0.54:80`) - we can verify that this IP is really the IP of our pod by running `kubectl get pod file-storage -o wide`.\n\n\n![Kubernetes](./image_09.png)\n\n\n\nIf no endpoint is found for `file-storage`, you should check that the spec.selector field of your Service actually selects for `metadata.labels` values on your Pods. A common mistake is to have a typo or other error, such as the Service selecting for `service: file-storage`, but the Deployment specifying `app: file-storage`.\n\n\nBoth the pod and the service are working and the services is finding our pod - everything seems to be as it should be... onward with [Troubleshooting the Ingress](#troubleshooting-the-nginx-ingress).\n\n\n\n### Adding it to our NGINX Ingress\n\n\nTo route traffic to our cluster we are using the [NGINX Ingress](https://mpolinowski.github.io/kubernetes-nginx-ingress/) - in theory we only have to add our service to the [Ingress Configuration](https://mpolinowski.github.io/kubernetes-nginx-ingress/#preparing-the-nginx-ingress) and assign it to a sub-URL that we want to use:\n\n\n__nginx-ingress.yaml__\n\n```yaml\napiVersion: extensions/v1beta1\nkind: Ingress\nmetadata:\n  name: nginx-ingress\nspec:\n  rules:\n  - http:\n      paths:\n        - path: /web\n          backend:\n            serviceName: web-service\n            servicePort: 5678\n        - path: /mobile\n          backend:\n            serviceName: mobile-service\n            servicePort: 5678\n        - path: /test\n          backend:\n            serviceName: test-service\n            servicePort: 3000\n        - path: /dl\n          backend:\n            serviceName: file-storage\n            servicePort: 80\n```\n\n__Note__ that we could use the annotation [ingress.kubernetes.io/rewrite-target: /](https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md#rewrite) to rewrite all incoming traffic to root. That means that, even though you are able to access the file storage app on `/dl` the app will register this traffic relative to `/` instead.\n\n\n```yaml\napiVersion: extensions/v1beta1\nkind: Ingress\nmetadata:\n  name: nginx-ingress\n  annotations:\n    ingress.kubernetes.io/rewrite-target: /\n    ...\n```\n\n\n![Kubernetes](./image_10.png)\n\n\nWe are now able to access the fileserver over the WAN IP address of your Kubernetes MASTER Server:\n\n\n![Kubernetes](./image_12.png)\n\n\n### Deployment\n\nWe can now delete the Pod and rewrite it as a __Kubernetes Deployment__\n\n\n__file-storage-development.yaml__\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: file-storage\n  labels:\n    app: file-storage\nspec:\n  selector:\n    matchLabels:\n      app: file-storage\n  strategy:\n    type: Recreate\n  template:\n    metadata:\n      labels:\n        app: file-storage\n    spec:\n      containers:\n      - name: file-storage-container\n        image: nginx\n        ports:\n        - containerPort: 80\n          name: file-server\n        volumeMounts:\n          - mountPath: \"/usr/share/nginx/html\"\n            name: file-storage-volume\n        imagePullPolicy: Always\n        resources: {}\n      volumes:\n        - name: file-storage-volume\n          persistentVolumeClaim:\n           claimName: file-storage-claim\n```\n\n\nCreate the development and verify that the Pod is running:\n\n\n```bash\nkubectl create -f file-storage-development.yaml\nkubectl get development file-storage\nkubectl get pods\n```\n\nThe pod should now be listed two blocks characters attached to the pod name - assigning it to your deployment and replicaset: e.g. `file-storage-74bdcc99c4-bhfnb`.\n\n\nYou can use the same troubleshooting we [used before](#create-a-pod) to check if the Pod is operational and [connected to your service](#troubleshooting-a-service).\n\n\n\n### Troubleshooting the NGINX Ingress\n\n\nThere are many ways to [troubleshoot the ingress-controller](https://github.com/kubernetes/ingress-nginx/blob/master/docs/troubleshooting.md). The following are basic troubleshooting methods to obtain more information.\n\n\n```bash\nkubectl get ing -n default\n```\n\n\nHere I already found my first mistake, I renamed the ingress during development and an older version of it was not deleted, when I applied the updated config. But deleting the dupe did not solve the issue that the ingress does not seem to work.\n\n\n```bash\nkubectl describe ing nginx-ingress -n default\n```\n\n\nThis command shows us if the service was bound correctly:\n\n\n```bash\nRules:\n  Host              Path  Backends\n  ----              ----  --------\n  my.domain.com  \n                    /dl      file-storage:80 (\u003cnone\u003e)\n```\n\n\nEverything looks fine - we can now go on to check the __Ingress Controller__ logs:\n\n\n```bash\nkubectl get pods -n ingress-nginx\nkubectl logs -f nginx-ingress-controller-797b884cbc-f5qdt -n ingress-nginx\n```\n\n\nIn my case the pod can be referenced as `nginx-ingress-controller-797b884cbc-f5qdt` inside the __ingress-nginx__ namespace. Running the log shows me that the Ingress is receiving the request I am sending via `https://my.domain.com/dl/test.txt`\n\n\n![Kubernetes](./image_11.png)\n\n\n... Ok, I found the error - it was a typo in my `nginx-ingress.yaml` ... But it is good to have gone through the debug steps once, makes everything a lot less scary `:)`\n\n\n\n### Adding TLS to your Ingress\n\nYou can generate a self-signed certificate and private key with:\n\n```\nopenssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${KEY_FILE} -out ${CERT_FILE} -subj \"/CN=${HOST}/O=${HOST}\"`\n```\n\nThen create the secret in the cluster via:\n\n```bash\nkubectl create secret tls ${CERT_NAME} --key ${KEY_FILE} --cert ${CERT_FILE}\n```\n\nIn my case I already use a domain name on my server, so I can head over and create my certificates with [Certbot](https://certbot.eff.org). Certbot will store the certificate inside a folder (named after your domain) inside `/etc/letsencrypt` - you will get both a `fullchain.pem` and `privkey.pem` file that you can use in the Kubernetes command above to add a Secret to your cluster:\n\n\n```bash\nkubectl create secret tls my-tls-secret --key /etc/letsencrypt/live/my.domain.com/privkey.pem --cert /etc/letsencrypt/live/my.domain.com/fullchain.pem\n```\n\nNow that we made our cluster aware of the existence of the TLS certificate, we can add it to our NGINX Ingress configuration file:\n\n\n__nginx-ingress.yaml__\n\n```yaml\napiVersion: extensions/v1beta1\nkind: Ingress\nmetadata:\n  name: nginx-ingress\n  annotations:\n    kubernetes.io/ingress.class: \"nginx\"\n    nginx.ingress.kubernetes.io/enable-cors: \"true\"\n    nginx.ingress.kubernetes.io/cors-allow-methods: \"GET, POST, PUT\"\n    nginx.ingress.kubernetes.io/http2-push-preload: \"true\"\nspec:\n  tls:\n  - hosts:\n    - my.domain.com\n    secretName: my-tls-secret\n  rules:\n  - http:\n      paths:\n        - path: /web\n          backend:\n            serviceName: web-service\n            servicePort: 5678\n        - path: /mobile\n          backend:\n            serviceName: mobile-service\n            servicePort: 5678\n        - path: /test\n          backend:\n            serviceName: test-service\n            servicePort: 3000\n        - path: /dl\n          backend:\n            serviceName: file-storage\n            servicePort: 80\n```\n\nFor more Annotations check the [official Documentation](https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md)\n\n\nYou can now access the file server over your domain name: `https://my.domain.com/dl/test.txt`:\n\n\n![Kubernetes](./image_13.png)\n\n\n\n\n### Volume Access Control\n\nStorage configured with a group ID (GID) allows writing only by Pods using the same GID. Mismatched or missing GIDs cause permission denied errors. To reduce the need for coordination with users, an administrator can annotate a PersistentVolume with a GID. Then the GID is automatically added to any Pod that uses the PersistentVolume.\n\n\nUse the _pv.beta.kubernetes.io/gid_ annotation as follows:\n\n\n__file-storage-pv.yaml__\n\n```yaml\nkind: PersistentVolume\napiVersion: v1\nmetadata:\n  name: file-storage-volume\n  annotations:\n    pv.beta.kubernetes.io/gid: \"1234\"\n  labels:\n    type: local\nspec:\n  storageClassName: manual\n  capacity:\n    storage: 5Gi\n  accessModes:\n    - ReadWriteOnce\n  hostPath:\n    path: \"/opt/filecontainer\"\n```\n\n\n\n__file-storage-pod.yaml__\n\n```yaml\nkind: Pod\napiVersion: v1\nmetadata:\n  name: file-storage-pod\n  annotations:\n    pv.beta.kubernetes.io/gid: \"1234\"\nspec:\n  volumes:\n    - name: file-storage-volume\n      persistentVolumeClaim:\n       claimName: file-storage-claim\n  containers:\n    - name: file-storage-container\n      image: nginx\n      ports:\n        - containerPort: 80\n          name: \"http-file-server\"\n      volumeMounts:\n        - mountPath: \"/usr/share/nginx/html\"\n          name: file-storage-volume\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpolinowski%2Fhttp-fileserver-kubernetes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmpolinowski%2Fhttp-fileserver-kubernetes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpolinowski%2Fhttp-fileserver-kubernetes/lists"}