Absensi Karyawan Gps Barcode
The skeleton application for the Laravel framework.
#Aplikasi Web Absensi Karyawan QR Code GPS
Aplikasi web absensi karyawan menggunakan QR Code dan GPS.
#Teknologi yang Digunakan
- Laravel 11/12
- Laravel Jetstream
- Endroid QR Code
- Leaflet.js
- OpenStreetMap
- MySQL/MariaDB
#Cara Menjalankan
Aplikasi ini tidak mewajibkan Docker. Tersedia dua cara yang setara, pilih salah satu:
- Instalasi tradisional: PHP, Composer, Node.js/Bun, dan MySQL dipasang langsung di mesin. Lihat bagian Instalasi.
- Docker Compose: seluruh stack berjalan di dalam container tanpa perlu tool apa pun di host. Lihat bagian Menjalankan dengan Docker dan Menjalankan di Produksi (Docker).
Perubahan kode aplikasi tidak membedakan kedua mode; file-file Docker (Dockerfile, folder docker/, docker-compose*.yml) hanya digunakan saat menjalankan lewat Docker.
#Instalasi
#Prasyarat
- Composer
- NPM & Node.js atau Bun
- PHP 8.3+
- MySQL/MariaDB/SQlite
-
Clone/download repository ini
-
Buat database (jika tidak menggunakan SQLite)
-- nama database sesuaikan dengan yang ada di .env CREATE DATABASE db_absensi_karyawan;
-
Jalankan perintah
# untuk membuat file `.env` composer run-script post-root-package-install # atau cp .env.example .env # untuk instalasi dependency php composer install # untuk instalasi dependency javascript npm install # atau bun install # untuk membuat key aplikasi php artisan key:generate --ansi --force # untuk menghubungkan storage ke public php artisan storage:link # untuk membuat tabel database [BUAT DATABASE DAHULU] php artisan migrate # untuk membuat file css dan javascript yang diperlukan npm run build # atau bun run build
Menjalankan aplikasi (local)
php artisan serve
#Seeder
Pilih salah satu opsi berikut:
-
Jalankan perintah berikut untuk menyiapkan data awal
php artisan db:seed DatabaseSeeder
-
(Recommended untuk development) Jalankan perintah berikut untuk menyiapkan data awal beserta data dummy (absensi & karyawan)
php artisan db:seed FakeDataSeeder
Akun default hasil seeder:
| Role | Password | |
|---|---|---|
| Super Admin | superadmin@example.com |
superadmin |
| Admin | admin@example.com |
admin |
#Menjalankan dengan Docker
Cara ini tidak membutuhkan PHP, Composer, Node.js/Bun, maupun MySQL di mesin host. Semuanya berjalan di dalam container.
#Prasyarat
#Menjalankan
-
Clone/download repository ini
-
Siapkan file
.env. Jika belum ada, salin dari contoh:cp .env.example .env
Nilai
DB_HOST,DB_PORT,DB_PASSWORD, danAPP_URLakan ditimpa olehenvironmentdi docker-compose.yml, jadi.envbawaan aman digunakan. -
Build dan jalankan stack (aplikasi + MySQL):
docker compose up -d -
Tunggu sampai container
absensi-appselesai inisialisasi. Pantau dengan:docker compose logs -f appSaat pertama kali dijalankan, container secara otomatis melakukan:
- setup permission
storage/danbootstrap/cache - menunggu database siap
- generate
APP_KEY(jika belum ada) migrate- seeder dasar (
DatabaseSeeder) hanya saat database masih kosong danAPP_ENV=local
- setup permission
-
Aplikasi bisa diakses di http://localhost:8000, login dengan akun hasil seeder pada tabel di atas.
#Seeder Data Dummy (FakeDataSeeder) di Docker
Seeder otomatis hanya menjalankan DatabaseSeeder. Untuk mengisi data dummy absensi dan karyawan:
# reset total database, lalu isi data awal + data dummy docker compose exec app php artisan migrate:fresh --force --seed --seeder=FakeDataSeeder # atau isi data dummy tanpa mereset data yang sudah ada docker compose exec app php artisan db:seed FakeDataSeeder --force
Setelah docker compose down -v (hapus volume), langkah up berikutnya akan otomatis migrate lagi dan menjalankan seeder dasar karena database kembali kosong.
#Tools Tambahan (Opsional)
phpMyAdmin dan Redis tersedia sebagai profile tools agar tidak ikut jalan secara default:
docker compose --profile tools up -d
- phpMyAdmin: http://localhost:8080
- MySQL juga terekspos ke host di port
3306(userroot, passwordsecret) - Redis di port
6379(belum dipakai aplikasi, disiapkan untuk scaling queue/cache)
#Perintah yang Sering Dipakai
# menjalankan artisan di dalam container docker compose exec app php artisan <perintah> # membuka tinker docker compose exec app php artisan tinker # melihat log aplikasi docker compose logs -f app # me-restart proses setelah mengubah kode PHP docker compose restart app # memberhentikan stack, data database tetap tersimpan docker compose down # memberhentikan stack sekaligus menghapus volume database/storage docker compose down -v
Catatan:
- Kode sumber di-bind-mount ke container sehingga perubahan langsung terlihat. Namun OPcache dikonfigurasi tanpa revalidasi (
opcache.validate_timestamps=0untuk performa produksi), jadi setelah mengedit file PHP jalankandocker compose restart app. - Konfigurasi container dibaca dari
env_file(docker/dev.envuntuk lokal,docker/prod.envuntuk produksi), bukan dari file.env. Variabel environment selalu menang atas.envyang mungkin ada di host. - Perintah
docker compose execberjalan sebagai root di dalam container. File yang dibuat artisan (misal hasil export XLSX) bisa berpemilik root; perbaiki denganchownbila diperlukan.
#Menjalankan di Produksi (Docker)
Mode produksi memakai overlay docker-compose.prod.yml yang digabung dengan compose dasar. Kredensial tidak lagi berasal dari docker/dev.env, melainkan dari docker/prod.env yang tidak pernah di-commit (sudah masuk .gitignore).
#Persiapan
-
Pastikan Docker dan Docker Compose terpasang di server, lalu clone repository.
-
Buat file environment produksi:
cp docker/prod.env.example docker/prod.env chmod 600 docker/prod.env nano docker/prod.env # isi semua nilai CHANGE_ME
-
Generate
APP_KEYsebelum start pertama, lalu tempel kedocker/prod.env:echo "APP_KEY=base64:$(openssl rand -base64 32)"
-
Isi kredensial database. Dua aturan penting:
DB_PASSWORDharus sama denganMYSQL_PASSWORDMYSQL_ROOT_PASSWORDwajib berbeda dari keduanya
Pasangan user
MYSQL_USER/MYSQL_PASSWORDhanya dibuat oleh image MySQL saat inisialisasi volume pertama kali. Jika volume sudah terlanjur ada, buat user secara manual atau hapus volume db sebelum start.
#Menjalankan
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
Saat start, entrypoint secara otomatis:
- menunggu database siap lalu menjalankan
migrate - membangun ulang cache konfigurasi, route, dan view (
config:cache,route:cache,view:cache) - menyalakan nginx, php-fpm, queue worker, dan scheduler via supervisord
Seeder tidak dijalankan otomatis di mode produksi. Jalankan manual bila benar-benar dibutuhkan:
docker compose exec app php artisan db:seed FakeDataSeeder --force
#Verifikasi
# health check internal docker compose exec app curl -f http://localhost:8000/up # status keempat proses docker compose exec app supervisorctl -c /etc/supervisor/conf.d/supervisord.conf status
#Reverse Proxy dan HTTPS
Secara default tidak ada port yang dipublish. Buka komentar pada blok ports di docker-compose.prod.yml agar aplikasi tersedia di 127.0.0.1:8000 host, lalu pasang reverse proxy di depannya untuk terminasi SSL:
server { listen 443 ssl; server_name absensi.perusahaan.co.id; ssl_certificate /etc/letsencrypt/live/absensi.perusahaan.co.id/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/absensi.perusahaan.co.id/privkey.pem; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
Header X-Forwarded-Proto https diperlukan agar Laravel menghasilkan URL https.
#Update Aplikasi
git pull docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
Entrypoint akan migrate skema baru dan membangun ulang semua cache saat boot, jadi tidak ada langkah manual setelah deploy.
#Backup Database
docker compose exec db sh -c 'mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE"' | gzip > backup-$(date +%F).sql.gz
Restore:
gunzip < backup-2026-08-25.sql.gz | docker compose exec -T db sh -c 'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE"'
#Ringkasan Variabel Sensitif di docker/prod.env
| Variabel | Fungsi |
|---|---|
APP_KEY |
Enkripsi session dan data terenkripsi; jangan diubah setelah produksi berjalan |
DB_PASSWORD + MYSQL_PASSWORD |
Password user aplikasi; kedua nilai harus identik |
MYSQL_ROOT_PASSWORD |
Password root MySQL untuk backup/administrasi |
MAIL_* |
Kredensial SMTP untuk email keluar |
APP_URL / ASSET_URL |
Domain publik; wajib benar agar asset dan link valid |
#Fitur & Pratinjau
#User/Karyawan
| Scan Page | Scan Page (Mobile) |
|---|---|
| Riwayat Absensi Karyawan | Pengajuan Izin | Riwayat Pengajuan Izin |
|---|---|---|
#Admin & Superadmin
| Dashboard Admin | Dashboard Admin Dark |
|---|---|
| Barcode | Create/Edit Barcode |
|---|---|
| Absensi Karyawan | ||
|---|---|---|
| Absensi per hari | Absensi per minggu | Absensi per bulan |
| Data Karyawan | Create/Edit Data Karyawan |
|---|---|
| Export/Import from/to XLSX | |
|---|---|
| Export/Import Data Karyawan & User | Export/Import Data Karyawan & User + Preview Data |
| Export/Import Data Absensi & User | Export/Import Data Absensi & User + Preview Data |
| Pengajuan Izin (Admin) | Detail Pengajuan Izin |
|---|---|
#Device Restriction
Fitur pembatasan login perangkat untuk mencegah titip absen. Device token (UUID) otomatis digenerate dan disimpan di localStorage browser saat login.
-
Login dari perangkat berbeda ditolak
-
Admin dapat mereset perangkat dari menu Employee
-
Admin & superadmin tidak terpengaruh
-
Dapat dinonaktifkan via .env:
DEVICE_RESTRICTION_ENABLED=false
#Status Incomplete
Karyawan yang absen masuk tapi pulang sebelum jam shift berakhir akan mendapatkan status 'Tidak Tuntas' (incomplete), bukan 'Hadir'. Deteksi otomatis saat scan keluar.
#Alur Pengajuan Izin
Pengajuan izin tidak langsung disetujui, melainkan melalui proses approval:
- Karyawan mengajukan izin/sakit via form
- Status pengajuan: Menunggu (pending)
- Admin menyetujui atau menolak pengajuan
- Jika disetujui, data absensi otomatis terisi untuk rentang tanggal tersebut
- Karyawan dapat melihat status pengajuannya di halaman Riwayat Izin
#Donasi ❤
Atau, beri star...⭐⭐⭐⭐